/*
 *	NVidia injector
 *
 *	Copyright (C) 2009	Jasmin Fazlic, iNDi
 *
 *	NVidia injector modified by Fabio (ErmaC) on May 2012,
 *	for allow the cosmetics injection also based on SubVendorID and SubDeviceID.
 *
 *	NVidia injector is free software: you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published by
 *	the Free Software Foundation, either version 3 of the License, or
 *	(at your option) any later version.
 *
 *	NVidia driver and injector is distributed in the hope that it will be useful,
 *	but WITHOUT ANY WARRANTY; without even the implied warranty of
 *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *	GNU General Public License for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with NVidia injector.	 If not, see <http://www.gnu.org/licenses/>.
 *
 *	Alternatively you can choose to comply with APSL
 *
 *	DCB-Table parsing is based on software (nouveau driver) originally distributed under following license:
 *
 *
 *	Copyright 2005-2006 Erik Waling
 *	Copyright 2006 Stephane Marchesin
 *	Copyright 2007-2009 Stuart Bennett
 *
 *	Permission is hereby granted, free of charge, to any person obtaining a
 *	copy of this software and associated documentation files (the "Software"),
 *	to deal in the Software without restriction, including without limitation
 *	the rights to use, copy, modify, merge, publish, distribute, sublicense,
 *	and/or sell copies of the Software, and to permit persons to whom the
 *	Software is furnished to do so, subject to the following conditions:
 *
 *	The above copyright notice and this permission notice shall be included in
 *	all copies or substantial portions of the Software.
 *
 *	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 *	THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *	WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 *	OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *	SOFTWARE.
 */

#include "Platform.h"
#include "nvidia.h"
#include "device_inject.h"

#ifndef DEBUG_NVIDIA
#ifndef DEBUG_ALL
#define DEBUG_NVIDIA 1
#else
#define DEBUG_NVIDIA DEBUG_ALL
#endif
#endif

#if DEBUG_NVIDIA == 0
#define DBG(...)
#else
#define DBG(...) DebugLog(DEBUG_NVIDIA, __VA_ARGS__)
#endif

CHAR8 generic_name[128];

const CHAR8 *nvidia_compatible_0[]        =	{ "@0,compatible",	"NVDA,NVMac"    };
const CHAR8 *nvidia_compatible_1[]        =	{ "@1,compatible",	"NVDA,NVMac"    };
const CHAR8 *nvidia_device_type_0[]       =	{ "@0,device_type", "display"       };
const CHAR8 *nvidia_device_type_1[]       =	{ "@1,device_type", "display"       };
const CHAR8 *nvidia_device_type_parent[]  =	{ "device_type",    "NVDA,Parent"   };
const CHAR8 *nvidia_device_type_child[]   =	{ "device_type",    "NVDA,Child"    };
const CHAR8 *nvidia_name_0[]              =	{ "@0,name",        "NVDA,Display-A"};
const CHAR8 *nvidia_name_1[]              =	{ "@1,name",        "NVDA,Display-B"};
//const CHAR8 *nvidia_slot_name[]           =	{ "AAPL,slot-name", "Slot-1"        };

UINT8 default_NVCAP[]= {
	0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
	0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
	0x00, 0x00, 0x00, 0x00
};

#define NVCAP_LEN ( sizeof(default_NVCAP) / sizeof(UINT8) )

UINT8 default_dcfg_0[]= {0x03, 0x01, 0x03, 0x00};
UINT8 default_dcfg_1[]= {0xff, 0xff, 0x00, 0x01};

#define DCFG0_LEN ( sizeof(default_dcfg_0) / sizeof(UINT8) )
#define DCFG1_LEN ( sizeof(default_dcfg_1) / sizeof(UINT8) )

UINT8 default_NVPM[]= {
	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00
};

#define NVPM_LEN ( sizeof(default_NVPM) / sizeof(UINT8) )

static nvidia_pci_info_t nvidia_card_vendors[] = {
	{ 0x10190000,	"Elitegroup" },
	{ 0x10250000,	"Acer" },
	{ 0x10280000,	"Dell" },
	{ 0x10330000,	"NEC" },
	{ 0x103C0000,	"HP" },
	{ 0x10430000,	"Asus" },
	{ 0x104D0000,	"Sony" },
	{ 0x105B0000,	"Foxconn" },
	{ 0x106B0000,	"Apple" },
	{ 0x10710000,	"Mitac" },
	{ 0x107B0000,	"Gateway" },
	{ 0x107D0000,	"Leadtek" },
	{ 0x109F0000,	"Trigem" },
	{ 0x10B00000,	"Gainward" },
	{ 0x10CF0000,	"Fujitsu" },
	{ 0x10DE0000,	"nVidia" },
	{ 0x11790000,	"Toshiba" },
	{ 0x12970000,	"Shuttle" },
	{ 0x13DC0000,	"Netbost" },
	{ 0x144D0000,	"Samsung" },
	{ 0x14580000,	"Gigabyte" },
	{ 0x14620000,	"MSI" },
	{ 0x14C00000,	"Compal" },
	{ 0x152D0000,	"Quanta" },
	{ 0x15540000,	"Prolink" },
	{ 0x15580000,	"Clevo" },
	{ 0x15690000,	"Palit" },
	{ 0x161F0000,	"Arima" },
 	{ 0x16310000,	"NEC" },
	{ 0x16420000,	"Bitland" },
	{ 0x16820000,	"XFX" },
	{ 0x17340000,	"Fujitsu" },
	{ 0x174B0000,	"PC Partner" },
	{ 0x17AA0000,	"Lenovo" },
 	{ 0x17C00000,	"Wistron" },
	{ 0x17FF0000,	"Benq" },
	{ 0x18490000,	"ASRock" },
	{ 0x18540000,	"LG" },
	{ 0x18640000,	"LG" },
	{ 0x18940000,	"LG" },
	{ 0x19610000,	"ESS" },
	{ 0x196E0000,	"PNY" },
	{ 0x19910000,	"Topstar" },
	{ 0x19DA0000,	"Zotac" },
	{ 0x19F10000,	"BFG" },
	{ 0x1ACC0000,	"Point of View" },
	{ 0x1B0A0000,	"Pegatron" },
	{ 0x1B130000,	"Jaton" },
	{ 0x34420000,	"Bihl" },
	{ 0x38420000,	"EVGA" },
	{ 0x73770000,	"Colorful" },
};

static nvidia_pci_info_t nvidia_card_generic[] = {
	// 0000 - 0040
	{ 0x10DE0000,	"Unknown" },
	// 0040 - 004F
  /*	{ 0x10DE0040,	"GeForce 6800 Ultra" },
   { 0x10DE0041,	"GeForce 6800" },
   { 0x10DE0042,	"GeForce 6800 LE" },
   { 0x10DE0043,	"GeForce 6800 XE" },
   { 0x10DE0044,	"GeForce 6800 XT" },
   { 0x10DE0045,	"GeForce 6800 GT" },
   { 0x10DE0046,	"GeForce 6800 GT" },
   { 0x10DE0047,	"GeForce 6800 GS" },
   { 0x10DE0048,	"GeForce 6800 XT" },
   { 0x10DE0049,	"NV40GL" },
   { 0x10DE004D,	"Quadro FX 3400" },
   { 0x10DE004E,	"Quadro FX 4000" },  */
	// 0050 - 005F
	// 0060 - 006F
	// 0070 - 007F
	// 0080 - 008F
	// 0090 - 009F
	{ 0x10DE0090,	"GeForce 7800 GTX" },
	{ 0x10DE0091,	"GeForce 7800 GTX" },
	{ 0x10DE0092,	"GeForce 7800 GT" },
	{ 0x10DE0093,	"GeForce 7800 GS" },
	{ 0x10DE0094,	"GeForce 7800SE/XT/LE/LT/ZT" },
	{ 0x10DE0095,	"GeForce 7800 SLI" },
	{ 0x10DE0098,	"GeForce Go 7800" },
	{ 0x10DE0099,	"GeForce Go 7800 GTX" },
	{ 0x10DE009D,	"Quadro FX 4500" },
	// 00A0 - 00AF
	// 00B0 - 00BF
	// 00C0 - 00CF
  /*	{ 0x10DE00C0,	"GeForce 6800 GS" },
   { 0x10DE00C1,	"GeForce 6800" },
   { 0x10DE00C2,	"GeForce 6800 LE" },
   { 0x10DE00C3,	"GeForce 6800 XT" },
   { 0x10DE00C8,	"GeForce Go 6800" },
   { 0x10DE00C9,	"GeForce Go 6800 Ultra" },
   { 0x10DE00CC,	"Quadro FX Go1400" },
   { 0x10DE00CD,	"Quadro FX 3450/4000 SDI" },
   { 0x10DE00CE,	"Quadro FX 1400" },
   // 00D0 - 00DF
   // 00E0 - 00EF
   // 00F0 - 00FF
   { 0x10DE00F1,	"GeForce 6600 GT" },
   { 0x10DE00F2,	"GeForce 6600" },
   { 0x10DE00F3,	"GeForce 6200" },
   { 0x10DE00F4,	"GeForce 6600 LE" },
   { 0x10DE00F5,	"GeForce 7800 GS" },
   { 0x10DE00F6,	"GeForce 6800 GS/XT" },
   { 0x10DE00F8,	"Quadro FX 3400/4400" },
   { 0x10DE00F9,	"GeForce 6800 Series GPU" },  */
	// 0100 - 010F
	// 0110 - 011F
	// 0120 - 012F
	// 0130 - 013F
	// 0140 - 014F
  /*	{ 0x10DE0140,	"GeForce 6600 GT" },
   { 0x10DE0141,	"GeForce 6600" },
   { 0x10DE0142,	"GeForce 6600 LE" },
   { 0x10DE0143,	"GeForce 6600 VE" },
   { 0x10DE0144,	"GeForce Go 6600" },
   { 0x10DE0145,	"GeForce 6610 XL" },
   { 0x10DE0146,	"GeForce Go 6600 TE/6200 TE" },
   { 0x10DE0147,	"GeForce 6700 XL" },
   { 0x10DE0148,	"GeForce Go 6600" },
   { 0x10DE0149,	"GeForce Go 6600 GT" },
   { 0x10DE014A,	"Quadro NVS 440" },
   { 0x10DE014B,	"NV43" },
   { 0x10DE014C,	"Quadro FX 550" },
   { 0x10DE014D,	"Quadro FX 550" },
   { 0x10DE014E,	"Quadro FX 540" },
   { 0x10DE014F,	"GeForce 6200" },
   // 0150 - 015F
   // 0160 - 016F
   { 0x10DE0160,	"GeForce 6500" },
   { 0x10DE0161,	"GeForce 6200 TurboCache(TM)" },
   { 0x10DE0162,	"GeForce 6200SE TurboCache(TM)" },
   { 0x10DE0163,	"GeForce 6200 LE" },
   { 0x10DE0164,	"GeForce Go 6200" },
   { 0x10DE0165,	"Quadro NVS 285" },
   { 0x10DE0166,	"GeForce Go 6400" },
   { 0x10DE0167,	"GeForce Go 6200" },
   { 0x10DE0168,	"GeForce Go 6400" },
   { 0x10DE0169,	"GeForce 6250" },
   { 0x10DE016A,	"GeForce 7100 GS" },
   { 0x10DE016C,	"NVIDIA NV44GLM" },
   { 0x10DE016D,	"NVIDIA NV44GLM" },  */
	// 0170 - 017F
	// 0180 - 018F
	// 0190 - 019F
	{ 0x10DE0190,	"GeForce 8800" },
	{ 0x10DE0191,	"GeForce 8800 GTX" },
	{ 0x10DE0192,	"GeForce 8800" },
	{ 0x10DE0193,	"GeForce 8800 GTS" },
	{ 0x10DE0194,	"GeForce 8800 Ultra" },
	{ 0x10DE0197,	"Tesla C870" },
	{ 0x10DE019D,	"Quadro FX 5600" },
	{ 0x10DE019E,	"Quadro FX 4600" },
	// 01A0 - 01AF
	// 01B0 - 01BF
	// 01C0 - 01CF
	// 01D0 - 01DF
	{ 0x10DE01D0,	"GeForce 7350 LE" },
	{ 0x10DE01D1,	"GeForce 7300 LE" },
	{ 0x10DE01D2,	"GeForce 7550 LE" },
	{ 0x10DE01D3,	"GeForce 7300 SE/7200 GS" },
	{ 0x10DE01D6,	"GeForce Go 7200" },
	{ 0x10DE01D7,	"GeForce Go 7300" },
	{ 0x10DE01D8,	"GeForce Go 7400" },
	{ 0x10DE01D9,	"GeForce Go 7450" },
	{ 0x10DE01DA,	"Quadro NVS 110M" },
	{ 0x10DE01DB,	"Quadro NVS 120M" },
	{ 0x10DE01DC,	"Quadro FX 350M" },
	{ 0x10DE01DD,	"GeForce 7500 LE" },
	{ 0x10DE01DE,	"Quadro FX 350" },
	{ 0x10DE01DF,	"GeForce 7300 GS" },
	// 01E0 - 01EF
	// 01F0 - 01FF
  /*	{ 0x10DE01F0,	"GeForce4 MX" },
   // 0200 - 020F
   // 0210 - 021F
   { 0x10DE0211,	"GeForce 6800" },
   { 0x10DE0212,	"GeForce 6800 LE" },
   { 0x10DE0215,	"GeForce 6800 GT" },
   { 0x10DE0218,	"GeForce 6800 XT" },
   // 0220 - 022F
   { 0x10DE0221,	"GeForce 6200" },
   { 0x10DE0222,	"GeForce 6200 A-LE" },
   { 0x10DE0228,	"NVIDIA NV44M" },
   // 0230 - 023F
   // 0240 - 024F
   { 0x10DE0240,	"GeForce 6150" },
   { 0x10DE0241,	"GeForce 6150 LE" },
   { 0x10DE0242,	"GeForce 6100" },
   { 0x10DE0243,	"NVIDIA C51" },
   { 0x10DE0244,	"GeForce Go 6150" },
   { 0x10DE0245,	"Quadro NVS 210S / GeForce 6150LE" },
   { 0x10DE0247,	"GeForce Go 6100" },
   // 0250 - 025F
   { 0x10DE025B,	"Quadro4 700 XGL" },  */
	// 0260 - 026F
	// 0270 - 027F
	// 0280 - 028F
	// 0290 - 029F
	{ 0x10DE0290,	"GeForce 7900 GTX" },
	{ 0x10DE0291,	"GeForce 7900 GT/GTO" },
	{ 0x10DE0292,	"GeForce 7900 GS" },
	{ 0x10DE0293,	"GeForce 7950 GX2" },
	{ 0x10DE0294,	"GeForce 7950 GX2" },
	{ 0x10DE0295,	"GeForce 7950 GT" },
	{ 0x10DE0296,	"G71" },
	{ 0x10DE0297,	"GeForce Go 7950 GTX" },
	{ 0x10DE0298,	"GeForce Go 7900 GS" },
	{ 0x10DE0299,	"GeForce Go 7900 GTX" },
	{ 0x10DE029A,	"Quadro FX 2500M" },
	{ 0x10DE029B,	"Quadro FX 1500M" },
	{ 0x10DE029C,	"Quadro FX 5500" },
	{ 0x10DE029D,	"Quadro FX 3500" },
	{ 0x10DE029E,	"Quadro FX 1500" },
	{ 0x10DE029F,	"Quadro FX 4500 X2" },
	// 02A0 - 02AF
	// 02B0 - 02BF
	// 02C0 - 02CF
	// 02D0 - 02DF
	// 02E0 - 02EF
	{ 0x10DE02E0,	"GeForce 7600 GT" },
	{ 0x10DE02E1,	"GeForce 7600 GS" },
	{ 0x10DE02E2,	"GeForce 7300 GT" },
	{ 0x10DE02E3,	"GeForce 7900 GS" },
	{ 0x10DE02E4,	"GeForce 7950 GT" },
	// 02F0 - 02FF
	// 0300 - 030F
  /*
   { 0x10DE0301,	"GeForce FX 5800 Ultra" },
   { 0x10DE0302,	"GeForce FX 5800" },
   { 0x10DE0308,	"Quadro FX 2000" },
   { 0x10DE0309,	"Quadro FX 1000" },
   // 0310 - 031F
   { 0x10DE0311,	"GeForce FX 5600 Ultra" },
   { 0x10DE0312,	"GeForce FX 5600" },
   { 0x10DE0314,	"GeForce FX 5600XT" },
   { 0x10DE031A,	"GeForce FX Go5600" },
   { 0x10DE031B,	"GeForce FX Go5650" },
   { 0x10DE031C,	"Quadro FX Go700" },
   // 0320 - 032F
   { 0x10DE0320,	"GeForce FX 5200" },
   { 0x10DE0321,	"GeForce FX 5200 Ultra" },
   { 0x10DE0322,	"GeForce FX 5200" },
   { 0x10DE0323,	"GeForce FX 5200 LE" },
   { 0x10DE0324,	"GeForce FX Go5200" },
   { 0x10DE0325,	"GeForce FX Go5250" },
   { 0x10DE0326,	"GeForce FX 5500" },
   { 0x10DE0328,	"GeForce FX Go5200 32M/64M" },
   { 0x10DE0329,	"GeForce FX Go5200" },
   { 0x10DE032A,	"Quadro NVS 55/280 PCI" },
   { 0x10DE032B,	"Quadro FX 500/600 PCI" },
   { 0x10DE032C,	"GeForce FX Go53xx Series" },
   { 0x10DE032D,	"GeForce FX Go5100" },
   { 0x10DE032F,	"NV34GL" },
   // 0330 - 033F
   { 0x10DE0330,	"GeForce FX 5900 Ultra" },
   { 0x10DE0331,	"GeForce FX 5900" },
   { 0x10DE0332,	"GeForce FX 5900XT" },
   { 0x10DE0333,	"GeForce FX 5950 Ultra" },
   { 0x10DE0334,	"GeForce FX 5900ZT" },
   { 0x10DE0338,	"Quadro FX 3000" },
   { 0x10DE033F,	"Quadro FX 700" },
   // 0340 - 034F
   { 0x10DE0341,	"GeForce FX 5700 Ultra" },
   { 0x10DE0342,	"GeForce FX 5700" },
   { 0x10DE0343,	"GeForce FX 5700LE" },
   { 0x10DE0344,	"GeForce FX 5700VE" },
   { 0x10DE0345,	"NV36.5" },
   { 0x10DE0347,	"GeForce FX Go5700" },
   { 0x10DE0348,	"GeForce FX Go5700" },
   { 0x10DE0349,	"NV36M Pro" },
   { 0x10DE034B,	"NV36MAP" },
   { 0x10DE034C,	"Quadro FX Go1000" },
   { 0x10DE034E,	"Quadro FX 1100" },
   { 0x10DE034F,	"NV36GL" },
   */
	// 0350 - 035F
	// 0360 - 036F
	// 0370 - 037F
	// 0380 - 038F
	{ 0x10DE038B,	"GeForce 7650 GS" },
	// 0390 - 039F
	{ 0x10DE0390,	"GeForce 7650 GS" },
	{ 0x10DE0391,	"GeForce 7600 GT" },
	{ 0x10DE0392,	"GeForce 7600 GS" },
	{ 0x10DE0393,	"GeForce 7300 GT" },
	{ 0x10DE0394,	"GeForce 7600 LE" },
	{ 0x10DE0395,	"GeForce 7300 GT" },
	{ 0x10DE0397,	"GeForce Go 7700" },
	{ 0x10DE0398,	"GeForce Go 7600" },
	{ 0x10DE0399,	"GeForce Go 7600 GT"},
	{ 0x10DE039A,	"Quadro NVS 300M" },
	{ 0x10DE039B,	"GeForce Go 7900 SE" },
	{ 0x10DE039C,	"Quadro FX 560M" },
	{ 0x10DE039E,	"Quadro FX 560" },
	// 03A0 - 03AF
	// 03B0 - 03BF
	// 03C0 - 03CF
	// 03D0 - 03DF
	{ 0x10DE03D0,	"GeForce 6150SE nForce 430" },
	{ 0x10DE03D1,	"GeForce 6100 nForce 405" },
	{ 0x10DE03D2,	"GeForce 6100 nForce 400" },
	{ 0x10DE03D5,	"GeForce 6100 nForce 420" },
	{ 0x10DE03D6,	"GeForce 7025 / nForce 630a" },
	// 03E0 - 03EF
	// 03F0 - 03FF
	// 0400 - 040F
	{ 0x10DE0400,	"GeForce 8600 GTS" },
	{ 0x10DE0401,	"GeForce 8600 GT" },
	{ 0x10DE0402,	"GeForce 8600 GT" },
	{ 0x10DE0403,	"GeForce 8600 GS" },
	{ 0x10DE0404,	"GeForce 8400 GS" },
	{ 0x10DE0405,	"GeForce 9500M GS" },
	{ 0x10DE0406,	"GeForce 8300 GS" },
	{ 0x10DE0407,	"GeForce 8600M GT" },
	{ 0x10DE0408,	"GeForce 9650M GS" },
	{ 0x10DE0409,	"GeForce 8700M GT" },
	{ 0x10DE040A,	"Quadro FX 370" },
	{ 0x10DE040B,	"Quadro NVS 320M" },
	{ 0x10DE040C,	"Quadro FX 570M" },
	{ 0x10DE040D,	"Quadro FX 1600M" },
	{ 0x10DE040E,	"Quadro FX 570" },
	{ 0x10DE040F,	"Quadro FX 1700" },
	// 0410 - 041F
	{ 0x10DE0410,	"GeForce GT 330" },
	// 0420 - 042F
	{ 0x10DE0420,	"GeForce 8400 SE" },
	{ 0x10DE0421,	"GeForce 8500 GT" },
	{ 0x10DE0422,	"GeForce 8400 GS" },
	{ 0x10DE0423,	"GeForce 8300 GS" },
	{ 0x10DE0424,	"GeForce 8400 GS" },
	{ 0x10DE0425,	"GeForce 8600M GS" },
	{ 0x10DE0426,	"GeForce 8400M GT" },
	{ 0x10DE0427,	"GeForce 8400M GS" },
	{ 0x10DE0428,	"GeForce 8400M G" },
	{ 0x10DE0429,	"Quadro NVS 140M" },
	{ 0x10DE042A,	"Quadro NVS 130M" },
	{ 0x10DE042B,	"Quadro NVS 135M" },
	{ 0x10DE042C,	"GeForce 9400 GT" },
	{ 0x10DE042D,	"Quadro FX 360M" },
	{ 0x10DE042E,	"GeForce 9300M G" },
	{ 0x10DE042F,	"Quadro NVS 290" },
	// 0430 - 043F
	// 0440 - 044F
	// 0450 - 045F
	// 0460 - 046F
	// 0470 - 047F
	// 0480 - 048F
	// 0490 - 049F
	// 04A0 - 04AF
	// 04B0 - 04BF
	// 04C0 - 04CF
	{ 0x10DE04C0,	"NVIDIA G78" },
	{ 0x10DE04C1,	"NVIDIA G78" },
	{ 0x10DE04C2,	"NVIDIA G78" },
	{ 0x10DE04C3,	"NVIDIA G78" },
	{ 0x10DE04C4,	"NVIDIA G78" },
	{ 0x10DE04C5,	"NVIDIA G78" },
	{ 0x10DE04C6,	"NVIDIA G78" },
	{ 0x10DE04C7,	"NVIDIA G78" },
	{ 0x10DE04C8,	"NVIDIA G78" },
	{ 0x10DE04C9,	"NVIDIA G78" },
	{ 0x10DE04CA,	"NVIDIA G78" },
	{ 0x10DE04CB,	"NVIDIA G78" },
	{ 0x10DE04CC,	"NVIDIA G78" },
	{ 0x10DE04CD,	"NVIDIA G78" },
	{ 0x10DE04CE,	"NVIDIA G78" },
	{ 0x10DE04CF,	"NVIDIA G78" },
	// 04D0 - 04DF
	// 04E0 - 04EF
	// 04F0 - 04FF
	// 0500 - 050F
	// 0510 - 051F
	// 0520 - 052F
	// 0530 - 053F
	{ 0x10DE0530,	"GeForce 7190M / nForce 650M" },
	{ 0x10DE0531,	"GeForce 7150M / nForce 630M" },
	{ 0x10DE0533,	"GeForce 7000M / nForce 610M" },
	{ 0x10DE053A,	"GeForce 7050 PV / nForce 630a" },
	{ 0x10DE053B,	"GeForce 7050 PV / nForce 630a" },
	{ 0x10DE053E,	"GeForce 7025 / nForce 630a" },
	// 0540 - 054F
	// 0550 - 055F
	// 0560 - 056F
	// 0570 - 057F
	// 0580 - 058F
	// 0590 - 059F
	// 05A0 - 05AF
	// 05B0 - 05BF
	// 05C0 - 05CF
	// 05D0 - 05DF
	// 05E0 - 05EF
	{ 0x10DE05E0,	"GeForce GTX 295" },
	{ 0x10DE05E1,	"GeForce GTX 280" },
	{ 0x10DE05E2,	"GeForce GTX 260" },
	{ 0x10DE05E3,	"GeForce GTX 285" },
	{ 0x10DE05E4,	"NVIDIA GT200" },
	{ 0x10DE05E5,	"NVIDIA GT200" },
	{ 0x10DE05E6,	"GeForce GTX 275" },
	{ 0x10DE05E7,	"nVidia Tesla C1060" },
	{ 0x10DE05E8,	"NVIDIA GT200" },
	{ 0x10DE05E9,	"NVIDIA GT200" },
	{ 0x10DE05EA,	"GeForce GTX 260" },
	{ 0x10DE05EB,	"GeForce GTX 295" },
	{ 0x10DE05EC,	"NVIDIA GT200" },
	{ 0x10DE05ED,	"Quadroplex 2200 D2" },
	{ 0x10DE05EE,	"NVIDIA GT200" },
	{ 0x10DE05EF,	"NVIDIA GT200" },
	// 05F0 - 05FF
	{ 0x10DE05F0,	"NVIDIA GT200" },
	{ 0x10DE05F1,	"NVIDIA GT200" },
	{ 0x10DE05F2,	"NVIDIA GT200" },
	{ 0x10DE05F3,	"NVIDIA GT200" },
	{ 0x10DE05F4,	"NVIDIA GT200" },
	{ 0x10DE05F5,	"NVIDIA GT200" },
	{ 0x10DE05F6,	"NVIDIA GT200" },
	{ 0x10DE05F7,	"NVIDIA GT200" },
	{ 0x10DE05F8,	"Quadroplex 2200 S4" },
	{ 0x10DE05F9,	"NVIDIA Quadro CX" },
	{ 0x10DE05FA,	"NVIDIA GT200" },
	{ 0x10DE05FB,	"NVIDIA GT200" },
	{ 0x10DE05FC,	"NVIDIA GT200" },
	{ 0x10DE05FD,	"Quadro FX 5800" },
	{ 0x10DE05FE,	"Quadro FX 4800" },
	{ 0x10DE05FF,	"Quadro FX 3800" },
	// 0600 - 060F
	{ 0x10DE0600,	"GeForce 8800 GTS" },
	{ 0x10DE0601,	"GeForce 9800 GT" },
	{ 0x10DE0602,	"GeForce 8800 GT" },
	{ 0x10DE0603,	"GeForce GT 230" },
	{ 0x10DE0604,	"GeForce 9800 GX2" },
	{ 0x10DE0605,	"GeForce 9800 GT" },
	{ 0x10DE0606,	"GeForce 8800 GS" },
	{ 0x10DE0607,	"GeForce GTS 240" },
	{ 0x10DE0608,	"GeForce 9800M GTX" },
	{ 0x10DE0609,	"GeForce 8800M GTS" },
	{ 0x10DE060A,	"GeForce GTX 280M" },
	{ 0x10DE060B,	"GeForce 9800M GT" },
	{ 0x10DE060C,	"GeForce 8800M GTX" },
	{ 0x10DE060D,	"GeForce 8800 GS" },
	{ 0x10DE060F,	"GeForce GTX 285M" },
	// 0610 - 061F
	{ 0x10DE0610,	"GeForce 9600 GSO" },
	{ 0x10DE0611,	"GeForce 8800 GT" },
	{ 0x10DE0612,	"GeForce 9800 GTX" },
	{ 0x10DE0613,	"GeForce 9800 GTX+" },
	{ 0x10DE0614,	"GeForce 9800 GT" },
	{ 0x10DE0615,	"GeForce GTS 250" },
	{ 0x10DE0617,	"GeForce 9800M GTX" },
	{ 0x10DE0618,	"GeForce GTX 260M" },
	{ 0x10DE0619,	"Quadro FX 4700 X2" },
	{ 0x10DE061A,	"Quadro FX 3700" },
	{ 0x10DE061B,	"Quadro VX 200" },
	{ 0x10DE061C,	"Quadro FX 3600M" },
	{ 0x10DE061D,	"Quadro FX 2800M" },
	{ 0x10DE061E,	"Quadro FX 3700M" },
	{ 0x10DE061F,	"Quadro FX 3800M" },
	// 0620 - 062F
	{ 0x10DE0620,	"NVIDIA G94" },
	{ 0x10DE0621,	"GeForce GT 230" },
	{ 0x10DE0622,	"GeForce 9600 GT" },
	{ 0x10DE0623,	"GeForce 9600 GS" },
	{ 0x10DE0624,	"NVIDIA G94" },
	{ 0x10DE0625,	"GeForce 9600 GSO 512"},
	{ 0x10DE0626,	"GeForce GT 130" },
	{ 0x10DE0627,	"GeForce GT 140" },
	{ 0x10DE0628,	"GeForce 9800M GTS" },
	{ 0x10DE0629,	"NVIDIA G94" },
	{ 0x10DE062A,	"GeForce 9700M GTS" },
	{ 0x10DE062B,	"GeForce 9800M GS" },
	{ 0x10DE062C,	"GeForce 9800M GTS" },
	{ 0x10DE062D,	"GeForce 9600 GT" },
	{ 0x10DE062E,	"GeForce 9600 GT" },
	{ 0x10DE062F,	"GeForce 9800 S" },
	// 0630 - 063F
	{ 0x10DE0630,	"GeForce 9700 S" },
	{ 0x10DE0631,	"GeForce GTS 160M" },
	{ 0x10DE0632,	"GeForce GTS 150M" },
	{ 0x10DE0633,	"NVIDIA G94" },
	{ 0x10DE0634,	"NVIDIA G94" },
	{ 0x10DE0635,	"GeForce 9600 GSO" },
	{ 0x10DE0636,	"NVIDIA G94" },
	{ 0x10DE0637,	"GeForce 9600 GT" },
	{ 0x10DE0638,	"Quadro FX 1800" },
	{ 0x10DE0639,	"NVIDIA G94" },
	{ 0x10DE063A,	"Quadro FX 2700M" },
	{ 0x10DE063B,	"NVIDIA G94" },
	{ 0x10DE063C,	"NVIDIA G94" },
	{ 0x10DE063D,	"NVIDIA G94" },
	{ 0x10DE063E,	"NVIDIA G94" },
	{ 0x10DE063F,	"NVIDIA G94" },
	// 0640 - 064F
	{ 0x10DE0640,	"GeForce 9500 GT" },
	{ 0x10DE0641,	"GeForce 9400 GT" },
	{ 0x10DE0642,	"GeForce 8400 GS" },
	{ 0x10DE0643,	"GeForce 9500 GT" },
	{ 0x10DE0644,	"GeForce 9500 GS" },
	{ 0x10DE0645,	"GeForce 9500 GS" },
	{ 0x10DE0646,	"GeForce GT 120" },
	{ 0x10DE0647,	"GeForce 9600M GT" },
	{ 0x10DE0648,	"GeForce 9600M GS" },
	{ 0x10DE0649,	"GeForce 9600M GT" },
	{ 0x10DE064A,	"GeForce 9700M GT" },
	{ 0x10DE064B,	"GeForce 9500M G" },
	{ 0x10DE064C,	"GeForce 9650M GT" },
	// 0650 - 065F
	{ 0x10DE0650,	"NVIDIA G96-825" },
	{ 0x10DE0651,	"GeForce G 110M" },
	{ 0x10DE0652,	"GeForce GT 130M" },
	{ 0x10DE0653,	"GeForce GT 120M" },
	{ 0x10DE0654,	"GeForce GT 220M" },
	{ 0x10DE0655,	"GeForce GT 120" },
	{ 0x10DE0656,	"GeForce 9650 S" },
	{ 0x10DE0657,	"NVIDIA G96" },
	{ 0x10DE0658,	"Quadro FX 380" },
	{ 0x10DE0659,	"Quadro FX 580" },
	{ 0x10DE065A,	"Quadro FX 1700M" },
	{ 0x10DE065B,	"GeForce 9400 GT" },
	{ 0x10DE065C,	"Quadro FX 770M" },
	{ 0x10DE065D,	"NVIDIA G96" },
	{ 0x10DE065E,	"NVIDIA G96" },
	{ 0x10DE065F,	"GeForce G210" },
	// 0660 - 066F
	// 0670 - 067F
	// 0680 - 068F
	// 0690 - 069F
	// 06A0 - 06AF
	{ 0x10DE06A0,	"NVIDIA GT214" },
	// 06B0 - 06BF
	{ 0x10DE06B0,	"NVIDIA GT214" },
	// 06C0 - 06CF
	{ 0x10DE06C0,	"GeForce GTX 480" },
	{ 0x10DE06C3,	"GeForce GTX D12U" },
	{ 0x10DE06C4,	"GeForce GTX 465" },
	{ 0x10DE06CA,	"GeForce GTX 480M" },
	{ 0x10DE06CD,	"GeForce GTX 470" },
	// 06D0 - 06DF
	{ 0x10DE06D1,	"Tesla C2050" },
	{ 0x10DE06D2,	"Tesla M2070" },
	{ 0x10DE06D8,	"Quadro 6000" },
	{ 0x10DE06D9,	"Quadro 5000" },
	{ 0x10DE06DA,	"Quadro 5000M" },
	{ 0x10DE06DC,	"Quadro 6000" },
	{ 0x10DE06DD,	"Quadro 4000" },
	{ 0x10DE06DE,	"Tesla M2050" },
	{ 0x10DE06DF,	"Tesla M2070-Q" },
	// 06E0 - 06EF
	{ 0x10DE06E0,	"GeForce 9300 GE" },
	{ 0x10DE06E1,	"GeForce 9300 GS" },
	{ 0x10DE06E2,	"GeForce 8400" },
	{ 0x10DE06E3,	"GeForce 8400 SE" },
	{ 0x10DE06E4,	"GeForce 8400 GS" },
	{ 0x10DE06E5,	"GeForce 9300M GS" },
	{ 0x10DE06E6,	"GeForce G100" },
	{ 0x10DE06E7,	"GeForce 9300 SE" },
	{ 0x10DE06E8,	"GeForce 9200M GE" },
	{ 0x10DE06E9,	"GeForce 9300M GS" },
	{ 0x10DE06EA,	"Quadro NVS 150M" },
	{ 0x10DE06EB,	"Quadro NVS 160M" },
	{ 0x10DE06EC,	"GeForce G 105M" },
	{ 0x10DE06ED,	"NVIDIA G98" },
	{ 0x10DE06EF,	"GeForce G 103M" },
	// 06F0 - 06FF
	{ 0x10DE06F0,	"NVIDIA G98" },
	{ 0x10DE06F1,	"GeForce G105M" },
	{ 0x10DE06F2,	"NVIDIA G98" },
	{ 0x10DE06F3,	"NVIDIA G98" },
	{ 0x10DE06F4,	"NVIDIA G98" },
	{ 0x10DE06F5,	"NVIDIA G98" },
	{ 0x10DE06F6,	"NVIDIA G98" },
	{ 0x10DE06F7,	"NVIDIA G98" },
	{ 0x10DE06F8,	"Quadro NVS 420" },
	{ 0x10DE06F9,	"Quadro FX 370 LP" },
	{ 0x10DE06FA,	"Quadro NVS 450" },
	{ 0x10DE06FB,	"Quadro FX 370M" },
	{ 0x10DE06FC,	"NVIDIA G98" },
	{ 0x10DE06FD,	"Quadro NVS 295" },
	{ 0x10DE06FE,	"NVIDIA G98" },
	{ 0x10DE06FF,	"HICx16 + Graphics" },
	// 0700 - 070F
	// 0710 - 071F
	// 0720 - 072F
	// 0730 - 073F
	// 0740 - 074F
	// 0750 - 075F
	// 0760 - 076F
	// 0770 - 077F
	// 0780 - 078F
	// 0790 - 079F
	// 07A0 - 07AF
	// 07B0 - 07BF
	// 07C0 - 07CF
	// 07D0 - 07DF
	// 07E0 - 07EF
	{ 0x10DE07E0,	"GeForce 7150 / nForce 630i" },
	{ 0x10DE07E1,	"GeForce 7100 / nForce 630i" },
	{ 0x10DE07E2,	"GeForce 7050 / nForce 630i" },
	{ 0x10DE07E3,	"GeForce 7050 / nForce 610i" },
	{ 0x10DE07E5,	"GeForce 7050 / nForce 620i" },
	// 07F0 - 07FF
	// 0800 - 080F
	// 0810 - 081F
	// 0820 - 082F
	// 0830 - 083F
	// 0840 - 084F
	{ 0x10DE0840,	"GeForce 8200M" },
	{ 0x10DE0844,	"GeForce 9100M G" },
	{ 0x10DE0845,	"GeForce 8200M G" },
	{ 0x10DE0846,	"GeForce 9200" },
	{ 0x10DE0847,	"GeForce 9100" },
	{ 0x10DE0848,	"GeForce 8300" },
	{ 0x10DE0849,	"GeForce 8200" },
	{ 0x10DE084A,	"nForce 730a" },
	{ 0x10DE084B,	"GeForce 9200" },
	{ 0x10DE084C,	"nForce 980a/780a SLI" },
	{ 0x10DE084D,	"nForce 750a SLI" },
	{ 0x10DE084F,	"GeForce 8100 / nForce 720a" },
	// 0850 - 085F
	// 0860 - 086F
	{ 0x10DE0860,	"GeForce 9300" },
	{ 0x10DE0861,	"GeForce 9400" },
	{ 0x10DE0862,	"GeForce 9400M G" },
	{ 0x10DE0863,	"GeForce 9400M" },
	{ 0x10DE0864,	"GeForce 9300" },
	{ 0x10DE0865,	"GeForce 9300" },
	{ 0x10DE0866,	"GeForce 9400M G" },
	{ 0x10DE0867,	"GeForce 9400" },
	{ 0x10DE0868,	"nForce 760i SLI" },
	{ 0x10DE0869,	"GeForce 9400" },
	{ 0x10DE086A,	"GeForce 9400" },
	{ 0x10DE086C,	"GeForce 9300 / nForce 730i" },
	{ 0x10DE086D,	"GeForce 9200" },
	{ 0x10DE086E,	"GeForce 9100M G" },
	{ 0x10DE086F,	"GeForce 8200M G" },
	// 0870 - 087F
	{ 0x10DE0870,	"GeForce 9400M" },
	{ 0x10DE0871,	"GeForce 9200" },
	{ 0x10DE0872,	"GeForce G102M" },
	{ 0x10DE0873,	"GeForce G205M" },
	{ 0x10DE0874,	"ION 9300M" },
	{ 0x10DE0876,	"ION 9400M" },
	{ 0x10DE087A,	"GeForce 9400" },
	{ 0x10DE087D,	"ION 9400M" },
	{ 0x10DE087E,	"ION LE" },
	{ 0x10DE087F,	"ION LE" }, // Tesla M2070-Q ??
	// 0880 - 088F
	// 0890 - 089F
	// 08A0 - 08AF
	{ 0x10DE08A0,	"GeForce 320M" },
	{ 0x10DE08A1,	"MCP89-MZT" },
	{ 0x10DE08A2,	"GeForce 320M" },
	{ 0x10DE08A3,	"GeForce 320M" },
	{ 0x10DE08A4,	"GeForce 320M" },
	{ 0x10DE08A5,	"GeForce 320M" },
	// 08B0 - 08BF
	{ 0x10DE08B0,	"MCP83 MMD" },
	{ 0x10DE08B1,	"GeForce 300M" },
	{ 0x10DE08B2,	"GeForce 300M" }, // MCP83-MJ
	{ 0x10DE08B3,	"MCP89 MM9" },
	// 08C0 - 08CF
	// 08D0 - 08DF
	// 08E0 - 08EF
	// 08F0 - 08FF
	// 0900 - 090F
	// 0910 - 091F
	// 0920 - 092F
	// 0930 - 093F
	// 0940 - 094F
	// 0950 - 095F
	// 0960 - 096F
	// 0970 - 097F
	// 0980 - 098F
	// 0990 - 099F
	// 09A0 - 09AF
	// 09B0 - 09BF
	// 09C0 - 09CF
	// 09D0 - 09DF
	// 09E0 - 09EF
	// 09F0 - 09FF
	// 0A00 - 0A0F
	// { 0x10DE0A00,	"NVIDIA GT212" },
	// 0A10 - 0A1F
	// { 0x10DE0A10,	"NVIDIA GT212" },
	// 0A20 - 0A2F
	{ 0x10DE0A20,	"GeForce GT 220" },
	{ 0x10DE0A21,	"D10M2-20" },
	{ 0x10DE0A22,	"GeForce 315" },
	{ 0x10DE0A23,	"GeForce 210" },
	{ 0x10DE0A26,	"GeForce 405" },
	{ 0x10DE0A27,	"GeForce 405" },
	{ 0x10DE0A28,	"GeForce GT 230" },
	{ 0x10DE0A29,	"GeForce GT 330M" },
	{ 0x10DE0A2A,	"GeForce GT 230M" },
	{ 0x10DE0A2B,	"GeForce GT 330M" },
	{ 0x10DE0A2C,	"NVS 5100M" },
	{ 0x10DE0A2D,	"GeForce GT 320M" },
	// 0A30 - 0A3F
	{ 0x10DE0A30,	"GeForce GT 330M" },
	{ 0x10DE0A32,	"GeForce GT 415" },
	{ 0x10DE0A34,	"GeForce GT 240M" },
	{ 0x10DE0A35,	"GeForce GT 325M" },
	{ 0x10DE0A38,	"Quadro 400" },
	{ 0x10DE0A3C,	"Quadro FX 880M" },
	{ 0x10DE0A3D,	"N10P-ES" },
	{ 0x10DE0A3F,	"GT216-INT" },
	// 0A40 - 0A4F
	// 0A50 - 0A5F
	// 0A60 - 0A6F
	{ 0x10DE0A60,	"GeForce G210" },
	{ 0x10DE0A61,	"NVS 2100" },
	{ 0x10DE0A62,	"GeForce 205" },
	{ 0x10DE0A63,	"GeForce 310" },
	{ 0x10DE0A64,	"ION" },
	{ 0x10DE0A65,	"GeForce 210" },
	{ 0x10DE0A66,	"GeForce 310" },
	{ 0x10DE0A67,	"GeForce 315" },
	{ 0x10DE0A68,	"GeForce G105M" },
	{ 0x10DE0A69,	"GeForce G105M" },
	{ 0x10DE0A6A,	"NVS 2100M" },
	{ 0x10DE0A6C,	"NVS 3100M" },
	{ 0x10DE0A6E,	"GeForce 305M" },
	{ 0x10DE0A6F,	"ION" },
	// 0A70 - 0A7F
	{ 0x10DE0A70,	"GeForce 310M" },
	{ 0x10DE0A71,	"GeForce 305M" },
	{ 0x10DE0A72,	"GeForce 310M" },
	{ 0x10DE0A73,	"GeForce 305M" },
	{ 0x10DE0A74,	"GeForce G210M" },
	{ 0x10DE0A75,	"GeForce G310M" },
	{ 0x10DE0A76,	"ION" },
	{ 0x10DE0A78,	"Quadro FX 380 LP" },
	// { 0x10DE0A79,	"N12M-NS-S" },
	{ 0x10DE0A7A,	"GeForce 315M" },
	{ 0x10DE0A7B,	"GeForce 505" },
	{ 0x10DE0A7C,	"Quadro FX 380M" },
	{ 0x10DE0A7D,	"N11M-ES" }, //SUBIDS
	{ 0x10DE0A7E,	"GT218-INT-S" },
	{ 0x10DE0A7F,	"GT218-INT-B" },
	// 0A80 - 0A8F
	// 0A90 - 0A9F
	// 0AA0 - 0AAF
	// 0AB0 - 0ABF
	// 0AC0 - 0ACF
	// 0AD0 - 0ADF
	// 0AE0 - 0AEF
	// 0AF0 - 0AFF
	// 0B00 - 0B0F
	// 0B10 - 0B1F
	// 0B20 - 0B2F
	// 0B30 - 0B3F
	// 0B40 - 0B4F
	// 0B50 - 0B5F
	// 0B60 - 0B6F
	// 0B70 - 0B7F
	// 0B80 - 0B8F
	// 0B90 - 0B9F
	// 0BA0 - 0BAF
	// 0BB0 - 0BBF
	// 0BC0 - 0BCF
	// 0BD0 - 0BDF
	// 0BE0 - 0BEF
	// 0BF0 - 0BFF
	// 0C00 - 0C0F
	// 0C10 - 0C1F
	// 0C20 - 0C2F
	// 0C30 - 0C3F
	// 0C40 - 0C4F
	// 0C50 - 0C5F
	// 0C60 - 0C6F
	// 0C70 - 0C7F
	// 0C80 - 0C8F
	// 0C90 - 0C9F
	// 0CA0 - 0CAF
	{ 0x10DE0CA0,	"GeForce GT 330 " },
	{ 0x10DE0CA2,	"GeForce GT 320" },
	{ 0x10DE0CA3,	"GeForce GT 240" },
	{ 0x10DE0CA4,	"GeForce GT 340" },
	{ 0x10DE0CA5,	"GeForce GT 220" },
	{ 0x10DE0CA7,	"GeForce GT 330" },
	{ 0x10DE0CA8,	"GeForce GTS 260M" },
	{ 0x10DE0CA9,	"GeForce GTS 250M" },
	{ 0x10DE0CAC,	"GeForce GT 220" },
	{ 0x10DE0CAD,	"N10E-ES" }, // SUBIDS
	{ 0x10DE0CAE,	"GT215-INT" },
	{ 0x10DE0CAF,	"GeForce GT 335M" },
	// 0CB0 - 0CBF
	{ 0x10DE0CB0,	"GeForce GTS 350M" },
	{ 0x10DE0CB1,	"GeForce GTS 360M" },
	{ 0x10DE0CBC,	"Quadro FX 1800M" },
	// 0CC0 - 0CCF
	// 0CD0 - 0CDF
	// 0CE0 - 0CEF
	// 0CF0 - 0CFF
	// 0D00 - 0D0F
	// 0D10 - 0D1F
	// 0D20 - 0D2F
	// 0D30 - 0D3F
	// 0D40 - 0D4F
	// 0D50 - 0D5F
	// 0D60 - 0D6F
	// 0D70 - 0D7F
	// 0D80 - 0D8F
	// 0D90 - 0D9F
	// 0DA0 - 0DAF
	// 0DB0 - 0DBF
	// 0DC0 - 0DCF
	{ 0x10DE0DC0,	"GeForce GT 440" },
	//  { 0x10DE0DC1,	"D12-P1-35" },
	//  { 0x10DE0DC2,	"D12-P1-35" },
	{ 0x10DE0DC4,	"GeForce GTS 450" },
	{ 0x10DE0DC5,	"GeForce GTS 450" },
	{ 0x10DE0DC6,	"GeForce GTS 450" },
	//  { 0x10DE0DCA,	"GF10x" },
	//  { 0x10DE0DCC,	"N12E-GS" },
	{ 0x10DE0DCD,	"GeForce GT 555M" },
	{ 0x10DE0DCE,	"GeForce GT 555M" },
	//  { 0x10DE0DCF,	"N12P-GT-B" },
	// 0DD0 - 0DDF
	{ 0x10DE0DD0,	"N11E-GT" },
	{ 0x10DE0DD1,	"GeForce GTX 460M" },
	{ 0x10DE0DD2,	"GeForce GT 445M" },
	{ 0x10DE0DD3,	"GeForce GT 435M" },
	{ 0x10DE0DD6,	"GeForce GT 550M" },
	{ 0x10DE0DD8,	"Quadro 2000" },
	{ 0x10DE0DDA,	"Quadro 2000M" },
	{ 0x10DE0DDE,	"GF106-ES" },
	{ 0x10DE0DDF,	"GF106-INT" },
	// 0DE0 - 0DEF
	{ 0x10DE0DE0,	"GeForce GT 440" },
	{ 0x10DE0DE1,	"GeForce GT 430" },
	{ 0x10DE0DE2,	"GeForce GT 420" },
	{ 0x10DE0DE3,	"GeForce GT 635M" },
	{ 0x10DE0DE4,	"GeForce GT 520" },
	{ 0x10DE0DE5,	"GeForce GT 530" },
	{ 0x10DE0DE8,	"GeForce GT 620M" },
	{ 0x10DE0DE9,	"GeForce GT 630M" },
	{ 0x10DE0DEA,	"GeForce GT 610M" },
	{ 0x10DE0DEB,	"GeForce GT 555M" },
	{ 0x10DE0DEC,	"GeForce GT 525M" },
	{ 0x10DE0DED,	"GeForce GT 520M" },
	{ 0x10DE0DEE,	"GeForce GT 415M" },
	{ 0x10DE0DEF,	"NVS 5400M" },
	// 0DF0 - 0DFF
	{ 0x10DE0DF0,	"GeForce GT 425M" },
	{ 0x10DE0DF1,	"GeForce GT 420M" },
	{ 0x10DE0DF2,	"GeForce GT 435M" },
	{ 0x10DE0DF3,	"GeForce GT 420M" },
	{ 0x10DE0DF4,	"GeForce GT 540M" },
	{ 0x10DE0DF5,	"GeForce GT 525M" },
	{ 0x10DE0DF6,	"GeForce GT 550M" },
	{ 0x10DE0DF7,	"GeForce GT 520M" },
	{ 0x10DE0DF8,	"Quadro 600" },
	{ 0x10DE0DF9,	"Quadro 500M" },
	{ 0x10DE0DFA,	"Quadro 1000M" },
	{ 0x10DE0DFC,	"NVS 5200M" },
	{ 0x10DE0DFE,	"GF108 ES" },
	{ 0x10DE0DFF,	"GF108 INT" },
	// 0E00 - 0E0F
	// 0E10 - 0E1F
	// 0E20 - 0E2F
	{ 0x10DE0E21,	"D12U-25" },
	{ 0x10DE0E22,	"GeForce GTX 460" },
	{ 0x10DE0E23,	"GeForce GTX 460 SE" },
	{ 0x10DE0E24,	"GeForce GTX 460" },
	{ 0x10DE0E25,	"D12U-50" },
	{ 0x10DE0E28,	"GeForce GTX 460" },
	// 0E30 - 0E3F
	{ 0x10DE0E30,	"GeForce GTX 470M" },
	{ 0x10DE0E31,	"GeForce GTX 485M" },
	{ 0x10DE0E32,	"N12E-GT" },
	{ 0x10DE0E38,	"GF104GL" },
	{ 0x10DE0E3A,	"Quadro 3000M" },
	{ 0x10DE0E3B,	"Quadro 4000M" },
	{ 0x10DE0E3E,	"GF104-ES" },
	{ 0x10DE0E3F,	"GF104-INT" },
	// 0E40 - 0E4F
	// 0E50 - 0E5F
	// 0E60 - 0E6F
	// 0E70 - 0E7F
	// 0E80 - 0E8F
	// 0E90 - 0E9F
	// 0EA0 - 0EAF
	// 0EB0 - 0EBF
	// 0EC0 - 0ECF
	// 0ED0 - 0EDF
	// 0EE0 - 0EEF
	// 0EF0 - 0EFF
	// 0F00 - 0F0F
	{ 0x10DE0F00,	"GeForce GT 630" },
	{ 0x10DE0F01,	"GeForce GT 620" },
	{ 0x10DE0F02,	"GeForce GT 730" },
	// 0F10 - 0F1F
	// 0F20 - 0F2F
	// 0F30 - 0F3F
	// 0F40 - 0F4F
	// 0F50 - 0F5F
	// 0F60 - 0F6F
	// 0F70 - 0F7F
	// 0F80 - 0F8F
	// 0F90 - 0F9F
	// 0FA0 - 0FAF
	// 0FB0 - 0FBF
  { 0x10DE0FBB,	"GeForce GTX 970" },
	// 0FC0 - 0FCF
	{ 0x10DE0FC0,	"GeForce GT 640" },
	{ 0x10DE0FC1,	"GeForce GT 640" },
	{ 0x10DE0FC2,	"GeForce GT 630" },
	{ 0x10DE0FC6,	"GeForce GTX 650" },
	{ 0x10DE0FC8,	"GeForce GT 740" },
	{ 0x10DE0FCD,	"GeForce GT 755M" },
	{ 0x10DE0FCE,	"GeForce GT 640M LE" },
	// 0FD0 - 0FDF
	{ 0x10DE0FD1,	"GeForce GT 650M" },
	{ 0x10DE0FD2,	"GeForce GT 640M" },
	{ 0x10DE0FD3,	"GeForce GT 640M LE" },
	{ 0x10DE0FD4,	"GeForce GTX 660M" },
	{ 0x10DE0FD5,	"GeForce GT 650M" },
	{ 0x10DE0FD8,	"GeForce GT 640M" },
	{ 0x10DE0FD9,	"GeForce GT 645M" },
	{ 0x10DE0FDA,	"GK107-ES-A1" },
	{ 0x10DE0FDB,	"GK107-ESP-A1" },
	{ 0x10DE0FDC,	"GK107-INT22-A1" },
	{ 0x10DE0FDF,	"GeForce GT 740M" },
	// 0FE0 - 0FEF
	{ 0x10DE0FE0,	"GeForce GTX 660M" },
	{ 0x10DE0FE1,	"GeForce GT 730M" },
	{ 0x10DE0FE3,	"GeForce GT 745M" },
	{ 0x10DE0FE4,	"GeForce GT 750M" },
	{ 0x10DE0FE5,	"GeForce K340 USM" },
	{ 0x10DE0FE6,	"NVS K1 USM" },
	{ 0x10DE0FE7,	"Generic K1 USM / GRID K100" },
	{ 0x10DE0FE9,	"GeForce GT 750M" },
	{ 0x10DE0FEA,	"GeForce GT 755M" },
	{ 0x10DE0FEF,	"GRID K340" },
	// 0FF0 - 0FFF
	{ 0x10DE0FF0,	"NB1Q" },
	{ 0x10DE0FF1,	"NVS 1000" },
	{ 0x10DE0FF2,	"GRID K1" },
	{ 0x10DE0FF3,	"Quadro K420" },
	{ 0x10DE0FF5,	"Tesla K1 USM" },
	{ 0x10DE0FF6,	"Quadro K1100M" },
	{ 0x10DE0FF7,	"Quadro K1 USM" }, // K1 USM / GRID K120Q / GRID K140Q
	{ 0x10DE0FF8,	"Quadro K500M" },
	{ 0x10DE0FF9,	"Quadro K2000D" },
	{ 0x10DE0FFA,	"Quadro K600" },
	{ 0x10DE0FFB,	"Quadro K2000M" },
	{ 0x10DE0FFC,	"Quadro K1000M" },
	{ 0x10DE0FFD,	"NVS 510" },
	{ 0x10DE0FFE,	"Quadro K2000" },
	{ 0x10DE0FFF,	"Quadro 410" },
	// 1000 - 100F
	{ 0x10DE1001,	"GeForce GTX TITAN Z" },
	{ 0x10DE1003,	"GeForce GTX Titan LE" },
	{ 0x10DE1004,	"GeForce GTX 780" },
	{ 0x10DE1005,	"GeForce GTX Titan" },
	{ 0x10DE1006,	"GeForce GTX 780 Ti" },
	{ 0x10DE1007,	"GeForce GTX 780" },
	{ 0x10DE1008,	"GeForce GTX 780 Ti" },
	{ 0x10DE100A,	"GeForce GTX 780 Ti" },
  //	{ 0x10DE100B,	"Graphics Device" }, // GK110
	{ 0x10DE100C,	"GeForce GTX Titan Black" },
	// 1010 - 101F
	{ 0x10DE101E,	"Tesla K20X" }, // GK110GL
	{ 0x10DE101F,	"Tesla K20" },
	// 1020 - 102F
	{ 0x10DE1020,	"Tesla K20X" },
	{ 0x10DE1021,	"Tesla K20Xm" },
	{ 0x10DE1022,	"Tesla K20c" },
	{ 0x10DE1023,	"Tesla K40m" },  // GK110BGL
	{ 0x10DE1024,	"Tesla K40c" },  // GK110BGL
	{ 0x10DE1026,	"Tesla K20s" },
	{ 0x10DE1027,	"Tesla K40st" }, // GK110BGL
	{ 0x10DE1028,	"Tesla K20m" },
	{ 0x10DE1029,	"Tesla K40s" }, // GK110BGL
	{ 0x10DE102A,	"Tesla K40t" }, // GK110BGL
  //	{ 0x10DE102B,	"Graphics Device" }, // GK110BGL
  //	{ 0x10DE102C,	"Graphics Device" }, // GK110BGL
	{ 0x10DE102D,	"Tesla K80" }, // GK110BGL (2x)
	{ 0x10DE102E,	"Tesla K40d" }, // GK110BGL
	{ 0x10DE102F,	"Tesla Stella Solo" }, // GK110BGL
	// 1030 - 103F
  //	{ 0x10DE1030,	"" }, // GK110
	{ 0x10DE103a,	"Quadro K6000" }, // GK110GL
	{ 0x10DE103c,	"Quadro K5200" }, // GK110GL
	{ 0x10DE103F,	"Tesla Stella SXM" }, // GK110
	// 1040 - 104F
	{ 0x10DE1040,	"GeForce GT 520" },
	//  { 0x10DE1041,	"D13M1-45" },
	{ 0x10DE1042,	"GeForce 510" },
	{ 0x10DE1048,	"GeForce 605" },
	{ 0x10DE1049,	"GeForce GT 620" },
	{ 0x10DE104A,	"GeForce GT 610" },
	{ 0x10DE104B,	"GeForce GT 625 (OEM)" },
	{ 0x10DE104C,	"GeForce GT 705" }, // GF119
	{ 0x10DE104D,	" GeForce GT 710" }, // GF119
	// 1050 - 105F
	{ 0x10DE1050,	"GeForce GT 520M" },
	{ 0x10DE1051,	"GeForce GT 520MX" },
	{ 0x10DE1052,	"GeForce GT 520M" },
	{ 0x10DE1054,	"GeForce GT 410M" },
	{ 0x10DE1055,	"GeForce 410M" },
	{ 0x10DE1056,	"Quadro NVS 4200M" },
	{ 0x10DE1057,	"Quadro NVS 4200M" },
	{ 0x10DE1058,	"GeForce GT 610M" },
	{ 0x10DE1059,	"GeForce 610M" },
	{ 0x10DE105A,	"GeForce 610M" },
	{ 0x10DE105B,	"GeForce 705A" },
	// 1060 - 106F
	// 1070 - 107F
	{ 0x10DE107C,	"Quadro NVS 315" },
	{ 0x10DE107D,	"Quadro NVS 310" },
	//  { 0x10DE107E,	"GF119-INT" },
	{ 0x10DE107F,	"GF119-ES" },
	// 1080 - 108F
	{ 0x10DE1080,	"GeForce GTX 580" },
	{ 0x10DE1081,	"GeForce GTX 570" },
	{ 0x10DE1082,	"GeForce GTX 560 Ti" },
	{ 0x10DE1083,	"D13U" },
	{ 0x10DE1084,	"GeForce GTX 560" },
	{ 0x10DE1086,	"GeForce GTX 570 HD" },
	{ 0x10DE1087,	"GeForce GTX 560 Ti-448" },
	{ 0x10DE1088,	"GeForce GTX 590" },
	{ 0x10DE1089,	"GeForce GTX 580" },
	{ 0x10DE108B,	"GeForce GTX 590" },
	//  { 0x10DE108C,	"D13U" },
	{ 0x10DE108E,	"Tesla C2090" },
	// 1090 - 109F
	{ 0x10DE1091,	"Tesla M2090" }, // X2090
	{ 0x10DE1094,	"Tesla M2075" },
	{ 0x10DE1096,	"Tesla C2075" },
	{ 0x10DE1098,	"D13U" },
	{ 0x10DE109A,	"Quadro 5010M" },
	{ 0x10DE109B,	"Quadro 7000" },
	// 10A0 - 10AF
	// 10B0 - 10BF
	// 10C0 - 10CF
	{ 0x10DE10C0,	"GeForce 9300 GS" },
	{ 0x10DE10C3,	"GeForce 8400 GS" },
	{ 0x10DE10C4,	"ION" },
	{ 0x10DE10C5,	"GeForce 405" },
	// 10D0 - 10DF
	{ 0x10DE10D8,	"Quadro NVS 300" },
	// 10E0 - 10EF
	// 10F0 - 10FF
	// 1100 - 110F
	// 1110 - 111F
	// 1120 - 112F
	{ 0x10DE1128,	"GeForce GTX 970M" },
	// 1130 - 113F
	// 1140 - 114F
	{ 0x10DE1140,	"GeForce GT 610M" },
	{ 0x10DE1141,	"GeForce 610M" },
	{ 0x10DE1142,	"GeForce 620M" },
	{ 0x10DE1143,	"N13P-GV" },
	{ 0x10DE1144,	"GF117" },
	{ 0x10DE1145,	"GF117" },
	{ 0x10DE1146,	"GF117" },
	{ 0x10DE1147,	"GF117" },
	{ 0x10DE1149,	"GF117-ES" },
	{ 0x10DE114A,	"GF117-INT" },
	{ 0x10DE114B,	"PCI-GEN3-B" },
	{ 0x10DE1150,	"N13M-NS" },
	// 1160 - 116F
	// 1170 - 117F
	// 1180 - 118F
	{ 0x10DE1180,	"GeForce GTX 680" },
	{ 0x10DE1182,	"GeForce GTX 760 Ti" },
	{ 0x10DE1183,	"GeForce GTX 660 Ti" },
	{ 0x10DE1184,	"GeForce GTX 770" },
	{ 0x10DE1185,	"GeForce GTX 660 OEM" },
	{ 0x10DE1187,	"GeForce GTX 760" },
	{ 0x10DE1188,	"GeForce GTX 690" },
	{ 0x10DE1189,	"GeForce GTX 670" },
	{ 0x10DE118A,	"GRID K520" },
	{ 0x10DE118B,	"GRID K200" }, // GRID K2 GeForce USM
	{ 0x10DE118C,	"GRID K2 NVS USM" }, // GK104
	{ 0x10DE118D,	"GRID K200 vGPU" }, // GK104GL
	{ 0x10DE118E,	"GeForce GTX 760 (192-bit)" },
	{ 0x10DE118F,	"Tesla K10" },
	// 1190 - 119F
	{ 0x10DE1191,	"GeForce GTX 760" }, // GK104
	{ 0x10DE1192,	"GeForce GK104" },
	{ 0x10DE1193,	"GeForce GTX 760 Ti" },
	{ 0x10DE1194,	"Tesla K8" }, // GK104
	{ 0x10DE1195,	"GeForce GTX 660" },
	{ 0x10DE1198,	"GeForce GTX 880M" },
	{ 0x10DE1199,	"GeForce GTX 870M" },
	{ 0x10DE119A,	"GeForce GTX 860M" },
	{ 0x10DE119D,	"GeForce GTX 775M" }, // Mac Edition
	{ 0x10DE119E,	"GeForce GTX 780M" }, // Mac Edition
	{ 0x10DE119F,	"GeForce GTX 780M" },
	// 11A0 - 11AF
	{ 0x10DE11A0,	"GeForce GTX 680M" },
	{ 0x10DE11A1,	"GeForce GTX 670MX" },
	{ 0x10DE11A2,	"GeForce GTX 675MX" }, // Mac Edition
	{ 0x10DE11A3,	"GeForce GTX 680MX" },
	{ 0x10DE11A7,	"GeForce GTX 675MX" },
	{ 0x10DE11AF,	"GRID IceCube" }, // GF104M
	// 11B0 - 11BF
	{ 0x10DE11B0,	"GRID K240Q" }, // K260Q vGPU
	{ 0x10DE11B1,	"GRID K2 Tesla USM" },
	{ 0x10DE11B4,	"Quadro K4200" },
	{ 0x10DE11B6,	"Quadro K3100M" },
	{ 0x10DE11B7,	"Quadro K4100M" },
	{ 0x10DE11B8,	"Quadro K5100M" },
	{ 0x10DE11BA,	"Quadro K5000" },
	{ 0x10DE11BB,	"Quadro 4100" },
	{ 0x10DE11BC,	"Quadro K5000M" },
	{ 0x10DE11BD,	"Quadro K4000M" },
	{ 0x10DE11BE,	"Quadro K3000M" },
	{ 0x10DE11BF,	"GRID K2" }, // GK104GL
	// 11C0 - 11CF
	{ 0x10DE11C0,	"GeForce GTX 660" },
	{ 0x10DE11C2,	"GeForce GTX 650 Ti BOOST" },
	{ 0x10DE11C3,	"GeForce GTX 650 Ti" },
	{ 0x10DE11C4,	"GeForce GTX 645" },
	{ 0x10DE11C6,	"GeForce GTX 650 Ti" },
	{ 0x10DE11C7,	"GeForce GTX 750 Ti" },
	{ 0x10DE11C8,	"GeForce GTX 650 OEM" },
	// 11D0 - 11DF
	{ 0x10DE11D0,	"GK106-INT353" },
	// 11E0 - 11EF
	{ 0x10DE11E0,	"GeForce GTX 770M" },
	{ 0x10DE11E1,	"GeForce GTX 765M" },
	{ 0x10DE11E2,	"GeForce GTX 765M" },
	{ 0x10DE11E3,	"GeForce GTX 760M" },
  //	{ 0x10DE11E7,	"GeForce " }, // GK106M
	// 11F0 - 11FF
	{ 0x10DE11FA,	"Quadro K4000" },
	{ 0x10DE11FC,	"Quadro K2100M" },
	{ 0x10DE11FF,	"NB1Q" }, //
	// 1200 - 120F
	{ 0x10DE1200,	"GeForce GTX 560 Ti" },
	{ 0x10DE1201,	"GeForce GTX 560" },
	{ 0x10DE1202,	"GeForce GTX 560 Ti" },
	{ 0x10DE1203,	"GeForce GTX 460 SE v2" },
	{ 0x10DE1205,	"GeForce GTX 460 v2" },
	{ 0x10DE1206,	"GeForce GTX 555" },
	{ 0x10DE1207,	"GeForce GT 645" },
	{ 0x10DE1208,	"GeForce GTX 560 SE" },
	{ 0x10DE1210,	"GeForce GTX 570M" },
	{ 0x10DE1211,	"GeForce GTX 580M" },
	{ 0x10DE1212,	"GeForce GTX 675M" },
	{ 0x10DE1213,	"GeForce GTX 670M" },
	{ 0x10DE121F,	"GF114-INT" },
	{ 0x10DE1240,	"GeForce GT 620M" },
	{ 0x10DE1241,	"GeForce GT 545" },
	{ 0x10DE1243,	"GeForce GT 545" },
	{ 0x10DE1244,	"GeForce GTX 550 Ti" },
	{ 0x10DE1245,	"GeForce GTS 450" },
	{ 0x10DE1246,	"GeForce GT 550M" },
	{ 0x10DE1247,	"GeForce GT 555M" },
	{ 0x10DE1248,	"GeForce GT 555M" },
	{ 0x10DE1249,	"GeForce GTS 450" },
	{ 0x10DE124B,	"GeForce GT 640" },
	{ 0x10DE124D,	"GeForce GT 555M" },
	{ 0x10DE1250,	"GF116-INT" },
	{ 0x10DE1251,	"GeForce GTX 560M" },
	// 1260 - 126F
	// 1270 - 127F
	// 1280 - 128F
	{ 0x10DE1280,	"GeForce GT 635" },
	{ 0x10DE1281,	"GeForce GT 710" },
	{ 0x10DE1282,	"GeForce GT 640" },
	{ 0x10DE1284,	"GeForce GT 630" },
	{ 0x10DE1286,	"GeForce GT 720" },
	{ 0x10DE1287,	"GeForce GT 730" }, // GK208
	{ 0x10DE1288,	"GeForce GT 720" }, // GK208
  { 0x10DE128b,	"GeForce GT 710" },
	// 1290 - 129F
	{ 0x10DE1290,	"GeForce GT 730M" },
	{ 0x10DE1291,	"GeForce GT 735M" },
	{ 0x10DE1292,	"GeForce GT 740M" },
	{ 0x10DE1293,	"GeForce GT 730M" },
	{ 0x10DE1294,	"GeForce GT 740M" },
	{ 0x10DE1295,	"GeForce GT 710M" },
	{ 0x10DE1296,	"GeForce 825M" }, // GK208M
	{ 0x10DE1298,	"GeForce GT 720M" },
	{ 0x10DE1299,	"GeForce 920M" }, // GK208M
	// 12A0 - 12AF
	{ 0x10DE12A0,	"GK208" },
	{ 0x10DE12AF,	"GK208-INT" },
	{ 0x10DE12B0,	"GK208-CS-Q" },
	{ 0x10DE12B9,	"Quadro K610M" },
	{ 0x10DE12BA,	"Quadro K510M" },
	// 12B0 - 12BF
	// 12C0 - 12CF
	// 12D0 - 12DF
	// 12E0 - 12EF
	// 12F0 - 12FF
	{ 0x10DE1340,	"GeForce 830M" },
	{ 0x10DE1341,	"GeForce 840M" },
	{ 0x10DE1346,	"GeForce 930M" }, // GM108M
	{ 0x10DE1347,	"GeForce 940M" }, // GM108M
	{ 0x10DE1348,	"GeForce 945M/945A" }, // GM108M
	{ 0x10DE1349,	"GeForce 930M" }, // GM108M
	{ 0x10DE134D,	"GeForce 940MX" }, // GM108M
	{ 0x10DE134E,	"GeForce 930MX" }, // GM108M
	{ 0x10DE134F,	"GeForce 920MX" }, // GM108M
	{ 0x10DE137A,	"Quadro K620M/M500M" }, // GM108GLM
   	{ 0x10DE137B,	"Quadro M520" },
	{ 0x10DE137D,	"GeForce 940A" }, // GM108M
	{ 0x10DE1380,	"GeForce GTX 750 Ti" },
	{ 0x10DE1381,	"GeForce GTX 750" },
	{ 0x10DE1382,	"GeForce GTX 745" },
  //	{ 0x10DE1383,	"Graphics Device" }, // GM107
	{ 0x10DE1389,	"GRID M3" }, // GM107
	{ 0x10DE1390,	"GeForce 845M" },
	{ 0x10DE1391,	"GeForce GTX 850M" },
	{ 0x10DE1392,	"GeForce GTX 860M" },
	{ 0x10DE1393,	"GeForce 840M" },
	{ 0x10DE1398,	"GeForce 845M" }, //
	{ 0x10DE139A,	"GeForce GTX 950M" }, // GM107
	{ 0x10DE139B,	"GeForce GTX 960M" }, // GM107
	{ 0x10DE139C,	"GeForce 940M" }, // GM107M
	{ 0x10DE139D,	"GeForce GTX 750 Ti" }, // GM107M
	{ 0x10DE13AD,	"GM107 INT52" }, //
	{ 0x10DE13AE,	"GM107 CS1" }, //
  //	{ 0x10DE13AF,	"Graphics Device" }, // GM107GLM
	{ 0x10DE13B0,	"GQuadro M2000M" }, // GM107GLM
	{ 0x10DE13B1,	"Quadro M1000M" }, // GM107GLM
	{ 0x10DE13B2,	"Quadro M600M" }, // GM107GLM
	{ 0x10DE13B3,	"Quadro K2200M" }, // GM107GLM
  	{ 0x10DE13B4,	"Quadro M620" },
   	{ 0x10DE13B6,	"Quadro M1200" },
	{ 0x10DE13B9,	"NVS 810" }, // GM107GL
	{ 0x10DE13BA,	"Quadro K2200" },
	{ 0x10DE13BB,	"Quadro K620" },
	{ 0x10DE13BC,	"Quadro K1200" },
	{ 0x10DE13BD,	"Tesla M40" }, // GM107GLM
	{ 0x10DE13BE,	"GM107 CS1" }, //
	{ 0x10DE13BF,	"GM107 INT52" }, //
	// 12B0 - 12BF
	{ 0x10DE13C0,	"GeForce GTX 980" }, // GM107GLM
  //	{ 0x10DE13C1,	"Graphics Device" }, // GM107GLM
	{ 0x10DE13C2,	"GeForce GTX 970" }, // GM107GLM
  //	{ 0x10DE13C3,	"Graphics Device" }, // GM107GLM
	{ 0x10DE13D7,	"GeForce GTX 980M" }, //
	{ 0x10DE13D8,	"GeForce GTX 970M" }, //
	{ 0x10DE13D9,	"GeForce GTX 965M" },
	{ 0x10DE13DA,	"GeForce GTX 980" }, // GM204M
  	{ 0x10DE13F0,	"Quadro M5000" }, // GM204GL
	{ 0x10DE13F1,	"Quadro M4000" }, // GM204GL
	{ 0x10DE13F2,	"Tesla M60" }, // GM204GL
	{ 0x10DE13F3,	"Tesla M6" }, // GM204GL
	{ 0x10DE13F8,	"Quadro M5000M" }, // GM204GLM
	{ 0x10DE13F9,	"Quadro M4000M" }, // GM204GLM
	{ 0x10DE13FA,	"Quadro M3000M" }, // GM204GLM
	{ 0x10DE13FB,	"Quadro M5500" }, // GM204GLM
	{ 0x10DE1401,	"GeForce GTX 960" }, //
	{ 0x10DE1402,	"GeForce GTX 950" }, //
	{ 0x10DE1406,	"GeForce GTX 960" }, // GM206
	{ 0x10DE1407,	"GeForce GTX 750 v2" }, // GM206
	{ 0x10DE1427,	"GeForce GTX 965M" }, // GM206M
  { 0x10DE1430,	"Quadro M2000" }, //
	{ 0x10DE1431,	"Tesla M4" }, // GM206GL
  	{ 0x10DE1436,	"Quadro M2200" },
  //	{ 0x10DE143F,	"Graphics Device" }, //
  //	{ 0x10DE1600,	"Graphics Device" }, //
  //	{ 0x10DE1601,	"Graphics Device" }, //
  //	{ 0x10DE1602,	"Graphics Device" }, //
  //	{ 0x10DE1603,	"Graphics Device" }, //
	{ 0x10DE1617,	"GeForce GTX 980M" }, //
	{ 0x10DE1618,	"GeForce GTX 970M" }, // GM204M
	{ 0x10DE1619,	"GeForce GTX 965M" }, // GM204M
	{ 0x10DE161A,	"GeForce GTX 980" }, // GM204M
  //	{ 0x10DE1630,	"Graphics Device" }, //
  //	{ 0x10DE1631,	"Graphics Device" }, //
  	{ 0x10DE1667,	"GeForce GTX 965M" }, // GM204M
  //	{ 0x10DE1780,	"Graphics Device" }, //
  //	{ 0x10DE1781,	"Graphics Device" }, //
  //	{ 0x10DE1782,	"Graphics Device" }, //
  //	{ 0x10DE1783,	"Graphics Device" }, //
	{ 0x10DE1789,	"GRID M3-3020" }, //
	{ 0x10DE1790,	"N15S-GX" }, //
	{ 0x10DE1791,	"N15P-GT" }, //
	{ 0x10DE1792,	"N15P-GX" }, //
  //	{ 0x10DE17B3,	"Quadro" }, //
  //	{ 0x10DE17BA,	"Quadro" }, //
  //	{ 0x10DE17BB,	"Quadro" }, //
  //	{ 0x10DE17BD,	"Graphics Device" }, //
	{ 0x10DE17BE,	"GM107 CS1" }, // GM107
  //	{ 0x10DE17C1,	"Graphics Device" }, //
	{ 0x10DE17C2,	"GeForce GTX Titan X" }, //
  { 0x10DE17C8,	"GeForce GTX 980 TI" }, //
  //	{ 0x10DE17EE,	"Graphics Device" }, //
  //	{ 0x10DE17EF,	"Graphics Device" }, //
	{ 0x10DE17F0,	"Quadro M6000" },
  //	{ 0x10DE17FF,	"Graphics Device" }, //
	{ 0x10DE17F1,	"Quadro M6000" }, // GM200GL
	{ 0x10DE17FD,	"Tesla M40" }, // GM200GL
	// 1B00 - 1CFFF
	{ 0x10DE1B00,   "Titan X Pascal"}, // GP102
  //	{ 0x10DE1B01,	"Graphics Device" }, // GP102
	{ 0x10DE1B30,	"Quadro P6000" }, // GP102GL
  //	{ 0x10DE1B70,	"Graphics Device" }, // GP102GL
  //	{ 0x10DE1B78,	"Graphics Device" }, // GP102GL
	{ 0x10DE1B80,   "GeForce GTX 1080"}, // GP104
	{ 0x10DE1B81,   "GeForce GTX 1070"}, // GP104
  //	{ 0x10DE1B82,	"Graphics Device" }, // GP104
  //	{ 0x10DE1B83,	"Graphics Device" }, // GP104
	{ 0x10DE1BA0,	"GeForce GTX 1080" }, // GP104M
	{ 0x10DE1BA1,	"GeForce GTX 1070" }, // GP104M
	{ 0x10DE1BB0,	"Quadro P5000" }, // GP104GL
  //	{ 0x10DE1BB1,	"Graphics Device" }, // GP104GL
  //	{ 0x10DE1BB4,	"Graphics Device" }, // GP104GL
  	{ 0x10DE1BB6,	"Quadro P5000" },
  	{ 0x10DE1BB7,	"Quadro P4000" },
  	{ 0x10DE1BB8,	"Quadro P3000" },
	{ 0x10DE1BE0,	"GeForce GTX 1080" }, //GP104M
	{ 0x10DE1BE1,	"GeForce GTX 1070" }, //GP104M
  //	{ 0x10DE1C00,	"Graphics Device" }, // GP106
  //	{ 0x10DE1C01,	"Graphics Device" }, // GP106
	{ 0x10DE1C02,   "GeForce GTX 1060"}, // GP106
	{ 0x10DE1C03,   "GeForce GTX 1060"}, // GP106
//	{ 0x10DE1C07,   "NVIDIA CMP6-1"}, //
	{ 0x10DE1c20,	"GeForce GTX 1060" }, //GP106M
  //	{ 0x10DE1C30,	"Graphics Device" }, // GP106GL
	{ 0x10DE1C60,	"GeForce GTX 1060" }, // GP106M
  //	{ 0x10DE1C70,	"Graphics Device" }, // GP106GL
  //	{ 0x10DE1C80,	"Graphics Device" }, // GP107
  //	{ 0x10DE1C81,	"Graphics Device" }, // GP107
  	{ 0x10DE1C82,	"GeForce GTX 1050 Ti"}, // GP107
	// 1D00 - 1EFFF
  	{ 0x10DE1D10,	"GeForce MX150"},

};

static nvidia_card_info_t nvidia_card_exceptions[] = {
  /* ========================================================================================
   * Layout is device(VendorId + DeviceId), subdev (SubvendorId + SubdeviceId), display name.
   * ========================================================================================
   */
  /* ------ Specific DeviceID and SubDevID. ------ */
	// 0000 - 00FF
	{ 0x10DE0040,	0x10438178,	"Asus V9999 Ultra V62.11" },
	{ 0x10DE0040,	0x1043817D,	"Asus V9999GT V61.21" },
	{ 0x10DE0040,	0x7FFFFFFF,	"GeForce 6800 Ultra [NV40.0]" },
	// 0100 - 01FF
	{ 0x10DE01D7,	0x102801C2,	"Dell Quadro NVS 110M" },
	{ 0x10DE01D7,	0x102801CC,	"Dell Quadro NVS 110M" },
	{ 0x10DE01D7,	0x10DE014B,	"nVidia Quadro NVS 110M" },
  
	{ 0x10DE01D8,	0x102801CC,	"Dell Quadro NVS 120M" },
	{ 0x10DE01D8,	0x10282003,	"Dell Quadro NVS 120M" },
  
	{ 0x10DE01DA,	0x10280407,	"Dell GeForce 7300 LE" },
	// 0200 - 02FF
	{ 0x10DE025B,	0x10480D23,	"ELSA Gloria4 700XGL" },
	// 0300 - 03FF
	{ 0x10DE0391,	0x10DE047A,	"Galaxy GeForce 7600 GT" },
	{ 0x10DE0391,	0x19F120DE,	"Galaxy GeForce 7600 GT" },
  
	{ 0x10DE0393,	0x00000400,	"Apple GeForce 7300GT" },
	// 0400 - 04FF
	{ 0x10DE0402,	0x10DE0439,	"Galaxy 8600GT" },
	{ 0x10DE0402,	0x10DE0505,	"Galaxy 8600GT" },
	// 0500 - 05FF
	{ 0x10DE05E2,	0x104382EB,	"ASUS ENGTX260" },
	{ 0x10DE05E2,	0x16822390,	"HFX GeForce GTX 260" },
	{ 0x10DE05E2,	0x17870000,	"HIS GeForce GTX 260" },
  
	{ 0x10DE05E6,	0x10B00401,	"Gainward GeForce GTX 285" },
  
	{ 0x10DE05E7,	0x10DE0595,	"nVidia Tesla T10 Processor" },
	{ 0x10DE05E7,	0x10DE066A,	"nVidia Tesla C1060" },
	{ 0x10DE05E7,	0x10DE068F,	"nVidia Tesla T10 Processor" },
	{ 0x10DE05E7,	0x10DE0697,	"nVidia Tesla M1060" },
	{ 0x10DE05E7,	0x10DE0714,	"nVidia Tesla M1060" },
	{ 0x10DE05E7,	0x10DE0743,	"nVidia Tesla M1060" },
	// 0600 - 06FF
	{ 0x10DE0600,	0x10DE0000,	"Abit GeForce 8800 GTS" },
  
	{ 0x10DE0605,	0x145834A2,	"Gigabyte GV-N98TOC-512H" },
  
	{ 0x10DE0608,	0x15880577,	"Solidum GeForce 9800M GTX" },
  
	{ 0x10DE0609,	0x11700121,	"Inventec GeForce 8800M GTS" },
  
	{ 0x10DE0612,	0x104382A6,	"Asus GeForce 9800 GTX+" },
	{ 0x10DE0612,	0x10DE0571,	"nVidia GeForce 9800 GTX+" },
	{ 0x10DE0612,	0x10DE0592,	"nVidia GeForce 9800 GTX+" },
	{ 0x10DE0612,	0x3842C842,	"EVGA GeForce 9800 GTX+" },
	{ 0x10DE0612,	0x3842C875,	"EVGA GeForce 9800 GTX+" },
  
	{ 0x10DE0615,	0x10480F67,	"ELSA GeForce GTS 250" },
	{ 0x10DE0615,	0x10DE0592,	"Palit GeForce GTS 250" },
	{ 0x10DE0615,	0x10DE0593,	"Palit GeForce GTS 250" },
	{ 0x10DE0615,	0x10DE0652,	"Palit GeForce GTS 250" },
	{ 0x10DE0615,	0x10DE0719,	"Palit GeForce GTS 250" },
	{ 0x10DE0615,	0x10DE079E,	"Palit GeForce GTS 250" },
	{ 0x10DE0615,	0x11503842,	"TMC GeForce GTS 250" }, // Thinking Machines Corporation
	{ 0x10DE0615,	0x11513842,	"JAE GeForce GTS 250" },
	{ 0x10DE0615,	0x11553842,	"Pine GeForce GTS 250" },
	{ 0x10DE0615,	0x11563842,	"Periscope GeForce GTS 250" },
  
	{ 0x10DE0618,	0x10432028,	"Asus GeForce GTX 170M" },
	{ 0x10DE0618,	0x1043202B,	"Asus GeForce GTX 680" },
  
	{ 0x10DE0622,	0x104382AC,	"Asus EN9600GT Magic" },
  
	{ 0x10DE0640,	0x10DE077F,	"Inno3D GeForce 9500GT HDMI" },
  
	{ 0x10DE0649,	0x1043202D,	"Asus GeForce GT 220M" },
  
	{ 0x10DE06CD,	0x10DE079F,	"Point of View GeForce GTX 470" },
	{ 0x10DE06CD,	0x14622220,	"MSI GeForce GTX 470 Twin Frozr II" },
  
	{ 0x10DE06D1,	0x10DE0771,	"nVidia Tesla C2050" },
	{ 0x10DE06D1,	0x10DE0772,	"nVidia Tesla C2070" },
  
	{ 0x10DE06D2,	0x10DE0774,	"nVidia Tesla M2070" },
	{ 0x10DE06D2,	0x10DE0830,	"nVidia Tesla M2070" },
	{ 0x10DE06D2,	0x10DE0842,	"nVidia Tesla M2070" },
	{ 0x10DE06D2,	0x10DE088F,	"nVidia Tesla X2070" },
	{ 0x10DE06D2,	0x10DE0908,	"nVidia Tesla M2070" },
  
	{ 0x10DE06DE,	0x10DE0773,	"nVidia Tesla S2050" },
	{ 0x10DE06DE,	0x10DE0830,	"nVidia Tesla M2070" },
	{ 0x10DE06DE,	0x10DE0831,	"nVidia Tesla M2070" },
	{ 0x10DE06DE,	0x10DE0832,	"nVidia Tesla M2070" },
	{ 0x10DE06DE,	0x10DE0840,	"nVidia Tesla X2070" },
  
	{ 0x10DE06E4,	0x10438322,	"Asus EN8400GS" },
	{ 0x10DE06E4,	0x14583475,	"GV-NX84S256HE [GeForce 8400 GS]" },
  
	{ 0x10DE06E8,	0x10280262,	"Dell GeForce 9200M GS" },
	{ 0x10DE06E8,	0x10280271,	"Dell GeForce 9200M GS" },
	{ 0x10DE06E8,	0x10280272,	"Dell GeForce 9200M GS" },
	{ 0x10DE06E8,	0x103C30F4,	"HP GeForce 9200M GS" },
	{ 0x10DE06E8,	0x103C30F7,	"HP GeForce 9200M GS" },
	{ 0x10DE06E8,	0x103C3603,	"HP GeForce 9200M GS" },
	// 0700 - 07FF
	// 0800 - 08FF
	{ 0x10DE0873,	0x104319B4,	"Asus GeForce G102M" },
	// 0900 - 09FF
	// 0A00 - 0AFF
	{ 0x10DE0A6F,	0x12974003,	"Shuttle XS 3510MA" },
  
	{ 0x10DE0A70,	0x17AA3605,	"Lenovo ION" },
  
	{ 0x10DE0A73,	0x17AA3607,	"Lenovo ION" },
	{ 0x10DE0A73,	0x17AA3610,	"Lenovo ION" },
  
	{ 0x10DE0A75,	0x17AA3605,	"Lenovo ION" },
	// 0B00 - 0BFF
	// 0C00 - 0CFF
	{ 0x10DE0CA3,	0x14628041,	"MSI VN240GT-MD1G" },
	{ 0x10DE0CA3,	0x16423926,	"Bitland GeForce GT 230" },
	// 0D00 - 0DFF
	{ 0x10DE0DD8,	0x10DE0914,	"nVidia Quadro 2000D" },
  
	{ 0x10DE0DEF,	0x17AA21F3,	"Lenovo NVS 5400M" },
	{ 0x10DE0DEF,	0x17AA21F4,	"Lenovo NVS 5400M" },
	{ 0x10DE0DEF,	0x17AA21F5,	"Lenovo NVS 5400M" },
	{ 0x10DE0DEF,	0x17AA21F6,	"Lenovo NVS 5400M" },
	{ 0x10DE0DEF,	0x17AA5005,	"Lenovo NVS 5400M" },
  
	// 0E00 - 0EFF
	{ 0x10DE0E22,	0x1043835D,	"Asus ENGTX460" },
  
	{ 0x10DE0E23,	0x10B00401,	"Gainward GeForce GTX 460" },
	// 0F00 - 0FFF
  { 0x10DE0FBB,	0x38422974,	"EVGA GTX 970 OC" },
	{ 0x10DE0FD2,	0x10280595,	"Dell GeForce GT 640M LE" },
	{ 0x10DE0FD2,	0x102805B2,	"Dell GeForce GT 640M LE" },
	// 1000 - 10FF
	{ 0x10DE1080,	0x14622561,	"MSI N580GTX Lightning" },
	{ 0x10DE1080,	0x14622563,	"MSI N580GTX Lightning" },
  
	{ 0x10DE1086,	0x10DE0871,	"Inno3D GeForce GTX 570" },
  
	{ 0x10DE1087,	0x104383D6,	"Asus ENGTX560Ti448 DCII" },
  
	{ 0x10DE1091,	0x10DE088E,	"nVidia Tesla X2090" },
	{ 0x10DE1091,	0x10DE0891,	"nVidia Tesla X2090" },
  
	{ 0x10DE1094,	0x10DE0888,	"nVidia Tesla M2075" },
  
	{ 0x10DE1096,	0x10DE0910,	"nVidia Tesla C2075" },
	{ 0x10DE1096,	0x10DE0911,	"nVidia Tesla C2050" },
  
	// 1100 - 11FF
	{ 0x10DE1140,	0x1025064A,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x1025064C,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250680,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250692,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250694,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250702,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250719,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250725,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250728,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x1025072B,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x1025072E,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10250732,	"Acer GeForce GT 620M" },
	{ 0x10DE1140,	0x10280565,	"Dell GeForce GT 630M" },
	{ 0x10DE1140,	0x10280568,	"Dell GeForce GT 630M" },
	{ 0x10DE1140,	0x144DC0D5,	"Samsung GeForce GT 630M" },
   	{ 0x10DE1140,	0x17AA2200,	"nVidia NVS 5200M" },
   	{ 0x10DE1140,	0x17AA2213,	"nVidia GeForce GT 720M" },
	{ 0x10DE1140,	0x17AA500D,	"Lenovo GeForce GT 620M" },
	{ 0x10DE1140,	0x1B0A20DD,	"Pegatron GeForce GT 620M" },
	{ 0x10DE1140,	0x1B0A20FD,	"Pegatron GeForce GT 620M" },
  
	{ 0x10DE1180,	0x00001255,	"Afox GTX 680" },
	{ 0x10DE1180,	0x104383F0,	"Asus GTX680-2GD5" },
	{ 0x10DE1180,	0x104383F6,	"Asus GTX 680 Direct CU II" },
	{ 0x10DE1180,	0x104383F7,	"Asus GTX 680 Direct CU II" },
	{ 0x10DE1180,	0x1458353C,	"GV-N680OC-2GD WindForce GTX 680 OC" },
	{ 0x10DE1180,	0x14622820,	"MSI N680GTX TwinFrozer" },
	{ 0x10DE1180,	0x14622830,	"MSI GTX 680 Lightning" },
	{ 0x10DE1180,	0x14622831,	"MSI GTX 680 Lightning LN2" },
	{ 0x10DE1180,	0x15691180,	"Palit GTX 680 JetStream" },
	{ 0x10DE1180,	0x15691181,	"Palit GTX 680 JetStream" },
	{ 0x10DE1180,	0x15691189,	"Palit GTX 680 JetStream" },
	{ 0x10DE1180,	0x38422682,	"EVGA GTX 680 SC" },
	{ 0x10DE1180,	0x38422683,	"EVGA GTX 680 SC" },
  
	{ 0x10DE1185,	0x10DE106F,	"nVidia GeForce GTX 760 OEM" }, // GK104
  
	{ 0x10DE1187,	0x14583614,	"GV-N760OC-4GD" },
  
	{ 0x10DE1189,	0x10438405,	"Asus GTX 670 Direct CU II TOP" },
	{ 0x10DE1189,	0x15691189,	"Palit GTX 670 JetStream" },
	{ 0x10DE1189,	0x19DA1255,	"Zotac GTX 670 AMP! Edition" },
  
	{ 0x10DE11A1,	0x15587102,	"Clevo N13E-GR" },
  
	{ 0x10DE11C0,	0x10DE0995,	"Inno3D GeForce GTX660" },
	{ 0x10DE11C0,	0x1458354E,	"GV-N660OC-2GD" },
  
	{ 0x10DE11C6,	0x1043842A,	"GTX650TI-1GD5" },
	// 1200 - 12FF
	{ 0x10DE1247,	0x10432119,	"Asus GeForce GT 670M" },
	{ 0x10DE1247,	0x10432120,	"Asus GeForce GT 670M" },
	{ 0x10DE1247,	0x1043212A,	"Asus GeForce GT 635M" },
	{ 0x10DE1247,	0x1043212B,	"Asus GeForce GT 635M" },
	{ 0x10DE1247,	0x1043212C,	"Asus GeForce GT 635M" },
	{ 0x10DE1247,	0x152D0930,	"Quanta GeForce GT 635M" },
  
	{ 0x10DE1248,	0x152D0930,	"Quanta GeForce GT 635M" },
  
	{ 0x10DE124D,	0x146210CC,	"MSi GeForce GT 635M" }
};

EFI_STATUS read_nVidia_PRAMIN(pci_dt_t *nvda_dev, VOID* rom, UINT16 arch)
{
	EFI_STATUS Status;
	EFI_PCI_IO_PROTOCOL		*PciIo;
	PCI_TYPE00			Pci;
  
  UINT32 vbios_vram = 0;
  UINT32 old_bar0_pramin = 0;
  
  DBG("read_nVidia_ROM\n");
  Status = gBS->OpenProtocol(nvda_dev->DeviceHandle, &gEfiPciIoProtocolGuid, (VOID**)&PciIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  if (EFI_ERROR(Status)) {
    return EFI_NOT_FOUND;
  }
  
  Status = PciIo->Pci.Read(PciIo,EfiPciIoWidthUint32, 0, sizeof(Pci) / sizeof(UINT32), &Pci);
  if (EFI_ERROR(Status)) {
    return EFI_NOT_FOUND;
  }
  
  if (arch >= 0x50) {
    DBG("Using PRAMIN fixups\n");
    /*Status = */PciIo->Mem.Read(
                                 PciIo,
                                 EfiPciIoWidthUint32,
                                 0,
                                 NV_PDISPLAY_OFFSET + 0x9f04,///4,
                                 1,
                                 &vbios_vram
                                 );
    vbios_vram = (vbios_vram & ~0xff) << 8;
    
    /*Status = */PciIo->Mem.Read(
                                 PciIo,
                                 EfiPciIoWidthUint32,
                                 0,
                                 NV_PMC_OFFSET + 0x1700,///4,
                                 1,
                                 &old_bar0_pramin
                                 );
    
    if (vbios_vram == 0)
      vbios_vram = (old_bar0_pramin << 16) + 0xf0000;
    
    vbios_vram >>= 16;
    
    /*Status = */PciIo->Mem.Write(
                                  PciIo,
                                  EfiPciIoWidthUint32,
                                  0,
                                  NV_PMC_OFFSET + 0x1700,///4,
                                  1,
                                  &vbios_vram
                                  );
  }
  
  Status = PciIo->Mem.Read(
                           PciIo,
                           EfiPciIoWidthUint8,
                           0,
                           NV_PRAMIN_OFFSET,
                           NVIDIA_ROM_SIZE,
                           rom
                           );
  
  if (arch >= 0x50) {
    /*Status = */PciIo->Mem.Write(
                                  PciIo,
                                  EfiPciIoWidthUint32,
                                  0,
                                  NV_PMC_OFFSET + 0x1700,///4,
                                  1,
                                  &old_bar0_pramin
                                  );
  }
  
  if (EFI_ERROR(Status)) {
    DBG("read_nVidia_ROM failed\n");
    return Status;
  }
  return EFI_SUCCESS;
}


EFI_STATUS read_nVidia_PROM(pci_dt_t *nvda_dev, VOID* rom)
{
	EFI_STATUS Status;
	EFI_PCI_IO_PROTOCOL		*PciIo;
	PCI_TYPE00            Pci;
  UINT32                value;
  
  DBG("PROM\n");
  Status = gBS->OpenProtocol(nvda_dev->DeviceHandle,
                             &gEfiPciIoProtocolGuid,
                             (VOID**)&PciIo,
                             gImageHandle,
                             NULL,
                             EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  if (EFI_ERROR(Status)) {
    return EFI_NOT_FOUND;
  }
  
  Status = PciIo->Pci.Read(PciIo,
                           EfiPciIoWidthUint32,
                           0,
                           sizeof(Pci) / sizeof(UINT32),
                           &Pci);
  if (EFI_ERROR(Status)) {
    return EFI_NOT_FOUND;
  }
  
  value = NV_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED;
  /*Status = */PciIo->Mem.Write(
                                PciIo,
                                EfiPciIoWidthUint32,
                                0,
                                NV_PBUS_PCI_NV_20*4,
                                1,
                                &value
                                );
  
  Status = PciIo->Mem.Read(
                           PciIo,
                           EfiPciIoWidthUint8,
                           0,
                           NV_PROM_OFFSET,
                           NVIDIA_ROM_SIZE,
                           rom
                           );
  
  value = NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED;
  /*Status = */PciIo->Mem.Write(
                                PciIo,
                                EfiPciIoWidthUint32,
                                0,
                                NV_PBUS_PCI_NV_20*4,
                                1,
                                &value
                                );
  
  if (EFI_ERROR(Status)) {
    DBG("read_nVidia_ROM failed\n");
    return Status;
  }
  return EFI_SUCCESS;
}

static INT32 patch_nvidia_rom(UINT8 *rom)
{
  UINT8 num_outputs = 0, i = 0;
  UINT8 dcbtable_version;
  UINT8 headerlength	 = 0;
  UINT8 numentries		 = 0;
  UINT8 recordlength	 = 0;
  UINT8 channel1 = 0, channel2 = 0;
  UINT16 dcbptr;
  UINT8 *dcbtable;
  UINT8 *togroup;
  INT32 has_lvds = FALSE;
  struct dcbentry {
    UINT8 type;
    UINT8 index;
    UINT8 *heads;
  } entries[MAX_NUM_DCB_ENTRIES];
  
//	DBG("patch_nvidia_rom\n");
	if (!rom || (rom[0] != 0x55 && rom[1] != 0xaa)) {
		DBG("FALSE ROM signature: 0x%02x%02x\n", rom[0], rom[1]);
		return PATCH_ROM_FAILED;
	}
  
  //	dcbptr = SwapBytes16(read16(rom, 0x36)); //double swap !!!
  dcbptr = *(UINT16*)&rom[0x36];
	if(!dcbptr) {
		DBG("no dcb table found\n");
		return PATCH_ROM_FAILED;
	}
  //	else
  //		DBG("dcb table at offset 0x%04x\n", dcbptr);
  
	dcbtable		= &rom[dcbptr];
	dcbtable_version	= dcbtable[0];
	
	if (dcbtable_version >= 0x20) {
		UINT32 sig;
		
		if (dcbtable_version >= 0x30) {
			headerlength = dcbtable[1];
			numentries	 = dcbtable[2];
			recordlength = dcbtable[3];
			sig = *(UINT32 *)&dcbtable[6];
		} else {
			sig = *(UINT32 *)&dcbtable[4];
			headerlength = 8;
		}
    
		if (sig != 0x4edcbdcb) {
			DBG("Bad display config block signature (0x%8x)\n", sig); //Azi: issue #48
			return PATCH_ROM_FAILED;
		}
	} else if (dcbtable_version >= 0x14) { /* some NV15/16, and NV11+ */
		CHAR8 sig[8]; // = { 0 };
		
		AsciiStrnCpyS(sig, 8, (CHAR8 *)&dcbtable[-7], 7);
    sig[7] = 0;
		recordlength = 10;
    
		if (AsciiStrCmp(sig, "DEV_REC")) {
			DBG("Bad Display Configuration Block signature (%a)\n", sig);
			return PATCH_ROM_FAILED;
		}
	} else {
		DBG("ERROR: dcbtable_version is 0x%X\n", dcbtable_version);
		return PATCH_ROM_FAILED;
	}
	
	if (numentries >= MAX_NUM_DCB_ENTRIES) {
		numentries = MAX_NUM_DCB_ENTRIES;
	}
  
	for (i = 0; i < numentries; i++) {
		UINT32 connection;
		connection = *(UINT32 *)&dcbtable[headerlength + recordlength * i];
    
		/* Should we allow discontinuous DCBs? Certainly DCB I2C tables can be discontinuous */
		if ((connection & 0x0000000f) == 0x0000000f) { /* end of records */
			continue;
		}
		if (connection == 0x00000000) { /* seen on an NV11 with DCB v1.5 */
			continue;
		}
		if ((connection & 0xf) == 0x6) { /* we skip type 6 as it doesnt appear on macbook nvcaps */
			continue;
		}
    
		entries[num_outputs].type = connection & 0xf;
		entries[num_outputs].index = num_outputs;
		entries[num_outputs++].heads = (UINT8*)&(dcbtable[(headerlength + recordlength * i) + 1]);
	}
	
	for (i = 0; i < num_outputs; i++) {
		if (entries[i].type == 3) {
			has_lvds =TRUE;
			//DBG("found LVDS\n");
			channel1 |= (0x1 << entries[i].index);
			entries[i].type = TYPE_GROUPED;
		}
	}
  
	// if we have a LVDS output, we group the rest to the second channel
	if (has_lvds) {
		for (i = 0; i < num_outputs; i++) {
			if (entries[i].type == TYPE_GROUPED) {
				continue;
			}
			channel2 |= (0x1 << entries[i].index);
			entries[i].type = TYPE_GROUPED;
		}
	} else {
		INT32 x;
		// we loop twice as we need to generate two channels
		for (x = 0; x <= 1; x++) {
			for (i=0; i<num_outputs; i++) {
				if (entries[i].type == TYPE_GROUPED) {
					continue;
				}
				// if type is TMDS, the prior output is ANALOG
				// we always group ANALOG and TMDS
				// if there is a TV output after TMDS, we group it to that channel as well
				if (i && entries[i].type == 0x2) {
					switch (x) {
						case 0:
							//DBG("group channel 1\n");
							channel1 |= (0x1 << entries[i].index);
							entries[i].type = TYPE_GROUPED;
              
							if (entries[i-1].type == 0x0) {
								channel1 |= (0x1 << entries[i-1].index);
								entries[i-1].type = TYPE_GROUPED;
							}
							// group TV as well if there is one
							if (((i+1) < num_outputs) && (entries[i+1].type == 0x1)) {
								//	DBG("group tv1\n");
								channel1 |= (0x1 << entries[i+1].index);
								entries[i+1].type = TYPE_GROUPED;
							}
							break;
              
						case 1:
							//DBG("group channel 2 : %d\n", i);
							channel2 |= ( 0x1 << entries[i].index);
							entries[i].type = TYPE_GROUPED;
              
							if (entries[i - 1].type == 0x0) {
								channel2 |= (0x1 << entries[i-1].index);
								entries[i-1].type = TYPE_GROUPED;
							}
							// group TV as well if there is one
							if (((i+1) < num_outputs) && (entries[i+1].type == 0x1)) {
								//	DBG("group tv2\n");
								channel2 |= ( 0x1 << entries[i+1].index);
								entries[i+1].type = TYPE_GROUPED;
							}
							break;
						default:
							break;
              
					}
					break;
				}
			}
		}
	}
	
	// if we have left ungrouped outputs merge them to the empty channel
	togroup = &channel2; // = (channel1 ? (channel2 ? NULL : &channel2) : &channel1);
  
	for (i = 0; i < num_outputs; i++) {
		if (entries[i].type != TYPE_GROUPED) {
			//DBG("%d not grouped\n", i);
			if (togroup) {
				*togroup |= (0x1 << entries[i].index);
			}
			entries[i].type = TYPE_GROUPED;
		}
	}
	
	if (channel1 > channel2) {
		UINT8 buff = channel1;
		channel1 = channel2;
		channel2 = buff;
	}
	
	default_NVCAP[6] = channel1;
	default_NVCAP[8] = channel2;
	
	// patching HEADS
	for (i = 0; i < num_outputs; i++) {
		if (channel1 & (1 << i)) {
			*entries[i].heads = 1;
		} else if(channel2 & (1 << i)) {
			*entries[i].heads = 2;
		}
	}
	return (has_lvds ? PATCH_ROM_SUCCESS_HAS_LVDS : PATCH_ROM_SUCCESS);
}

CHAR8 *get_nvidia_model(UINT32 device_id, UINT32 subsys_id, CARDLIST * nvcard)
{
	INT32 i, j;
  //DBG("get_nvidia_model for (%08x, %08x)\n", device_id, subsys_id);
  
	//ErmaC added selector for nVidia "old" style in System Profiler
  //DBG("NvidiaGeneric = %s\n", gSettings.NvidiaGeneric?L"YES":L"NO");
	if (gSettings.NvidiaGeneric == FALSE) {
    // First check in the plist, (for e.g this can override any hardcoded devices)
    //CARDLIST * nvcard = FindCardWithIds(device_id, subsys_id);
    if (nvcard && (nvcard->Id == device_id) && (nvcard->SubId == subsys_id)) {
      return nvcard->Model;
    }
    
    // Then check the exceptions table
    if (subsys_id) {
      for (i = 0; i < (sizeof(nvidia_card_exceptions) / sizeof(nvidia_card_exceptions[0])); i++) {
        if ((nvidia_card_exceptions[i].device == device_id) &&
            (nvidia_card_exceptions[i].subdev == subsys_id)) {
          return nvidia_card_exceptions[i].name_model;
        }
      }
    }
	}
  
	// At last try the generic names
	for (i = 1; i < (sizeof(nvidia_card_generic) / sizeof(nvidia_card_generic[0])); i++) {
    if (nvidia_card_generic[i].device == device_id) {
      //--
			//ErmaC added selector for nVidia "old" style in System Profiler
			if (gSettings.NvidiaGeneric) {
				DBG("Apply NvidiaGeneric\n");
				AsciiSPrint(generic_name, 128, "NVIDIA %a", nvidia_card_generic[i].name_model);
				return &generic_name[0]; // generic_name;
			}
      //			DBG("Not applied NvidiaGeneric\n");
      //--
			if (subsys_id) {
				for (j = 0; j < (sizeof(nvidia_card_vendors) / sizeof(nvidia_card_vendors[0])); j++) {
					if (nvidia_card_vendors[j].device == (subsys_id & 0xffff0000)) {
						AsciiSPrint(generic_name, 128, "%a %a",
                        nvidia_card_vendors[j].name_model,
                        nvidia_card_generic[i].name_model);
						return &generic_name[0]; // generic_name;
					}
				}
			}
			return nvidia_card_generic[i].name_model;
		}
	}
	return nvidia_card_generic[0].name_model;
}

UINT8 connector_type_1[]= {0x00, 0x08, 0x00, 0x00};
UINT32	boot_display = 1;

static INT32 devprop_add_nvidia_template(DevPropDevice *device, INTN n_ports)
{
  INTN    pnum;
  CHAR8 nkey[24];
  CHAR8 nval[24];
  
//	DBG("devprop_add_nvidia_template\n");
  
	if (!device) {
		return 0;
	}
  
  for (pnum = 0; pnum < n_ports; pnum++) {
    AsciiSPrint(nkey, 24, "@%d,name", pnum);
    AsciiSPrint(nval, 24, "NVDA,Display-%c", (65+pnum));
    //DBG("Nvidia: insert [%a : %a]\n", nkey, nval);
    devprop_add_value(device, nkey, (UINT8*)nval, 14);
    
    AsciiSPrint(nkey, 24, "@%d,compatible", pnum);
    devprop_add_value(device, nkey, (UINT8*)"NVDA,NVMac", 10);
    
    AsciiSPrint(nkey, 24, "@%d,device_type", pnum);
    devprop_add_value(device, nkey, (UINT8*)"display", 7);
    
    AsciiSPrint(nkey, 24, "@%d,display-cfg", pnum);
    if (pnum == 0) {
      devprop_add_value(device, nkey, (gSettings.Dcfg[0] != 0) ? &gSettings.Dcfg[0] : default_dcfg_0, DCFG0_LEN);
    } else {
      devprop_add_value(device, nkey, (gSettings.Dcfg[1] != 0) ? &gSettings.Dcfg[4] : default_dcfg_1, DCFG1_LEN);
    }
  }
  
  if (devices_number == 1) {
    devprop_add_value(device, "device_type", (UINT8*)"NVDA,Parent", 11);
  } else {
    devprop_add_value(device, "device_type", (UINT8*)"NVDA,Child", 10);
  }
  
	return 1;
}

UINT64 mem_detect(UINT16 nvCardType, pci_dt_t *nvda_dev)
{
	UINT64 vram_size = 0;
  /*
   // First check if any value exist in the plist
   CARDLIST * nvcard = FindCardWithIds(((nvda_dev->vendor_id << 16) | nvda_dev->device_id),((nvda_dev->subsys_id.subsys.vendor_id << 16) | nvda_dev->subsys_id.subsys.device_id));
   if (nvcard) {
   if (nvcard->VideoRam > 0) {
   // VideoRam * 1024 * 1024 == VideoRam << 20
   vram_size = LShiftU64(nvcard->VideoRam, 20);
   DBG("mem assigned %ld\n", vram_size);
   return vram_size;
   }
   }
   */
	if (nvCardType < NV_ARCH_50) {
		vram_size  = (UINT64)(REG32(nvda_dev->regs, NV04_PFB_FIFO_DATA));
		vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
	} else if (nvCardType < NV_ARCH_C0) {
		vram_size = (UINT64)(REG32(nvda_dev->regs, NV04_PFB_FIFO_DATA));
		vram_size |= LShiftU64(vram_size & 0xff, 32);
		vram_size &= 0xffffffff00ll;
	} else { // >= NV_ARCH_C0
		vram_size = LShiftU64(REG32(nvda_dev->regs, NVC0_MEM_CTRLR_RAM_AMOUNT), 20);
    //		vram_size *= REG32(nvda_dev->regs, NVC0_MEM_CTRLR_COUNT);
    vram_size = MultU64x32(vram_size, REG32(nvda_dev->regs, NVC0_MEM_CTRLR_COUNT));
	}
  
	// Then, Workaround for 9600M GT, GT 210/420/430/440/525M/540M & GTX 560M
	switch (nvda_dev->device_id) {
		case 0x0647: // 9600M GT 0647
			vram_size = 512*1024*1024;
			break;
		case 0x0649:	// 9600M GT 0649
			// 10DE06491043202D 1GB VRAM
			if (((nvda_dev->subsys_id.subsys.vendor_id << 16) | nvda_dev->subsys_id.subsys.device_id) == 0x1043202D) {
			  vram_size = 1024*1024*1024;
			}
			break;
		case 0x0A65: // GT 210
		case 0x0DE0: // GT 440
		case 0x0DE1: // GT 430
		case 0x0DE2: // GT 420
		case 0x0DEC: // GT 525M 0DEC
		case 0x0DF4: // GT 540M
		case 0x0DF5: // GT 525M 0DF5
			vram_size = 1024*1024*1024;
			break;
		case 0x1251: // GTX 560M
			vram_size = 1536*1024*1024;
			break;
		default:
			break;
	}
	DBG("mem_detected %ldMb\n", (vram_size >> 20));
	return vram_size;
}

BOOLEAN setup_nvidia_devprop(pci_dt_t *nvda_dev)
{
	const         INT32 MAX_BIOS_VERSION_LENGTH = 32;
	EFI_STATUS		Status = EFI_NOT_FOUND;
	DevPropDevice	*device = NULL;
	CHAR8         *devicepath = NULL;
  BOOLEAN				load_vbios = gSettings.LoadVBios;
  BOOLEAN				Injected = FALSE;
	UINT8         *rom = NULL;
	UINT16				nvCardType = 0;
	UINT64				videoRam = 0;
	UINT32				bar[7];
  //	UINT32				boot_display = 0;
  //UINT32        subsystem;
	INT32         nvPatch = 0;
	CHAR8         *model = NULL;
	CHAR16				FileName[64];
	UINT8         *buffer = NULL;
	UINTN         bufferLen = 0;
	UINTN         j, n_ports = 0;
	UINTN         i, version_start;
	INT32         crlf_count = 0;
	option_rom_pci_header_t		*rom_pci_header;
	CHAR8*				s;
	CHAR8*				s1;
	CHAR8*				version_str = (CHAR8*)AllocateZeroPool(MAX_BIOS_VERSION_LENGTH);
  BOOLEAN       RomAssigned = FALSE;
  UINT32        device_id, subsys_id;
  CARDLIST      *nvcard;
  
	devicepath = get_pci_dev_path(nvda_dev);
	bar[0] = pci_config_read32(nvda_dev, PCI_BASE_ADDRESS_0);
	nvda_dev->regs = (UINT8 *)(UINTN)(bar[0] & ~0x0f);
  //  subsystem = (nvda_dev->subsys_id.subsys.vendor_id << 16) +
  //  nvda_dev->subsys_id.subsys.device_id;
  device_id = ((nvda_dev->vendor_id << 16) | nvda_dev->device_id);
  subsys_id = ((nvda_dev->subsys_id.subsys.vendor_id << 16) | nvda_dev->subsys_id.subsys.device_id);
  
	// get card type
	nvCardType = (REG32(nvda_dev->regs, 0) >> 20) & 0x1ff;
  
  // First check if any value exist in the plist
  nvcard = FindCardWithIds(device_id, subsys_id);
  if (nvcard) {
    if (nvcard->VideoRam > 0) {
      // VideoRam * 1024 * 1024 == VideoRam << 20
      //videoRam = LShiftU64(nvcard->VideoRam, 20);
      videoRam = nvcard->VideoRam;
      model = nvcard->Model;
      n_ports = nvcard->VideoPorts;
      load_vbios = nvcard->LoadVBios;
      //DBG("mem assigned %ld\n", vram_size);
    }
  } else {
    
    // Amount of VRAM in Mb
    if (gSettings.VRAM != 0) {
      videoRam = gSettings.VRAM << 20;
    } else {
      videoRam = mem_detect(nvCardType, nvda_dev);
    }
	}
  
  if (gSettings.NvidiaGeneric) {
    // Get Model from the PCI
    //    model = get_nvidia_model(((nvda_dev->vendor_id << 16) | nvda_dev->device_id), subsystem);
    if (model == NULL) { // !nvcard->Model
      model = get_nvidia_model(device_id, subsys_id, NULL);
    }
  } else {
    
    for (j = 0; j < NGFX; j++) {
      if ((gGraphics[j].Vendor == Nvidia) && (gGraphics[j].DeviceID == nvda_dev->device_id)) {
        model = gGraphics[j].Model; //menu setting
        if (n_ports == 0) { // !nvcard->VideoPorts
          n_ports = gGraphics[j].Ports;
        }
        if (load_vbios == FALSE) { // !nvcard->LoadVBios
          load_vbios = gGraphics[j].LoadVBios;
        }
        break;
      }
    }
  }
  
  
  if (load_vbios) {
    UnicodeSPrint(FileName, 128, L"ROM\\10de_%04x_%04x_%04x.rom", nvda_dev->device_id, nvda_dev->subsys_id.subsys.vendor_id, nvda_dev->subsys_id.subsys.device_id);
    
    if (FileExists(OEMDir, FileName)) {
      DBG("Found specific VBIOS ROM file (10de_%04x_%04x_%04x.rom)\n", nvda_dev->device_id, nvda_dev->subsys_id.subsys.vendor_id, nvda_dev->subsys_id.subsys.device_id);
      
      Status = egLoadFile(OEMDir, FileName, &buffer, &bufferLen);
    } else {
      UnicodeSPrint(FileName, 128, L"ROM\\10de_%04x.rom", nvda_dev->device_id);
      if (FileExists(OEMDir, FileName)) {
        DBG("Found generic VBIOS ROM file (10de_%04x.rom)\n", nvda_dev->device_id);
        
        Status = egLoadFile(OEMDir, FileName, &buffer, &bufferLen);
      }
    }
    
    UnicodeSPrint(FileName, 128, L"\\EFI\\CLOVER\\ROM\\10de_%04x_%04x_%04x.rom", nvda_dev->device_id, nvda_dev->subsys_id.subsys.vendor_id, nvda_dev->subsys_id.subsys.device_id);
    if (EFI_ERROR(Status)) {
      if (FileExists(SelfRootDir, FileName)) {
        DBG("Found specific VBIOS ROM file (10de_%04x_%04x_%04x.rom)\n", nvda_dev->device_id, nvda_dev->subsys_id.subsys.vendor_id, nvda_dev->subsys_id.subsys.device_id);
        
        Status = egLoadFile(SelfRootDir, FileName, &buffer, &bufferLen);
      } else {
        UnicodeSPrint(FileName, 128, L"\\EFI\\CLOVER\\ROM\\10de_%04x.rom", nvda_dev->device_id);
        
        if (FileExists(SelfRootDir, FileName)) {
          DBG("Found generic VBIOS ROM file (10de_%04x.rom)\n", nvda_dev->device_id);
          
          Status = egLoadFile(SelfRootDir, FileName, &buffer, &bufferLen);
        }
      }
    }
  }
  
  if (EFI_ERROR(Status)) {
    rom = AllocateZeroPool(NVIDIA_ROM_SIZE+1);
    // PRAMIN first
    read_nVidia_PRAMIN(nvda_dev, rom, nvCardType);
    
    //DBG("%x%x\n", rom[0], rom[1]);
    rom_pci_header = NULL;
    
    if (rom[0] != 0x55 || rom[1] != 0xaa) {
      read_nVidia_PROM(nvda_dev, rom);
      if (rom[0] != 0x55 || rom[1] != 0xaa) {
        DBG("ERROR: Unable to locate nVidia Video BIOS\n");
        FreePool(rom);
        rom = NULL;
      }
    }
  }
  
  if (!rom){
    if (buffer) {
      if (buffer[0] != 0x55 && buffer[1] != 0xaa) {
        //DBG("buffer->size: %d\n", bufferLen);
        i = 0;
        while (i < bufferLen) {
          //DBG("%x%x\n", buffer[i], buffer[i+1]);
          if (buffer[i] == 0x55 && buffer[i+1] == 0xaa) {
            DBG(" header found at: %d\n", i);
            bufferLen -= i;
            rom = AllocateZeroPool(bufferLen);
            for (j = 0; j < bufferLen; j++) {
              rom[j] = buffer[i+j];
            }
            break;
          }
          i += 512;
        }
      }
      if (!rom) rom = buffer;
      RomAssigned = TRUE;
      DBG(" using loaded ROM image\n");
    } else {
      DBG(" there are no ROM loaded and no VBIOS read from hardware\n");
      //      return FALSE;
    }
  }
  
  if(rom) {
    
    if ((nvPatch = patch_nvidia_rom(rom)) == PATCH_ROM_FAILED) {
      DBG("ERROR: nVidia ROM Patching Failed!\n");
    }
    rom_pci_header = (option_rom_pci_header_t*)(rom + *(UINT16 *)&rom[24]);
    
    // check for 'PCIR' sig
    if (rom_pci_header->signature == 0x52494350) {
      if (rom_pci_header->device_id != nvda_dev->device_id) {
        // Get Model from the OpROM
        model = get_nvidia_model(((rom_pci_header->vendor_id << 16) | rom_pci_header->device_id), subsys_id, nvcard);
        //				DBG(model);
      }
    } else {
      DBG("nVidia incorrect PCI ROM signature: 0x%x\n", rom_pci_header->signature);
    }
    
    // get bios version
    
    // only search the first 384 bytes
    for (i = 0; i < 0x180; i++) {
      if (rom[i] == 0x0D && rom[i+1] == 0x0A) {
        crlf_count++;
        // second 0x0D0A was found, extract bios version
        if (crlf_count == 2) {
          if (rom[i-1] == 0x20) i--; // strip last " "
          
          for (version_start = i; version_start > (i-MAX_BIOS_VERSION_LENGTH); version_start--) {
            // find start
            if (rom[version_start] == 0x00) {
              version_start++;
              
              // strip "Version "
              if (AsciiStrnCmp((const CHAR8*)rom + version_start, "Version ", 8) == 0) {
                version_start += 8;
              }
              s = (CHAR8*)(rom + version_start);
              s1 = version_str;
              while ((*s > ' ') && (*s < 'z') && ((INTN)(s1 - version_str) < MAX_BIOS_VERSION_LENGTH)) {
                *s1++ = *s++;
              }
              *s1 = 0;
              DBG("version %a\n", version_str);
              break;
            }
          }
          break;
        }
      }
    }
  } else {
    AsciiSPrint(version_str, sizeof(version_str), "1.0");
  }
  
  DBG("nVidia %a ", model);
  DBG(" %dMB NV%02x [%04x:%04x] :: %a => device #%d\n", (UINT32)(RShiftU64(videoRam, 20)),
      nvCardType, nvda_dev->vendor_id, nvda_dev->device_id,
      devicepath, devices_number);
  
  if (!string) {
    string = devprop_create_string();
  }
  
  device = devprop_add_device_pci(string, nvda_dev);
  
  DBG("Nvidia: VideoPorts:");
  if (n_ports > 0) {
    DBG(" user defined (GUI-menu): %d\n", n_ports);
  } else if (gSettings.VideoPorts > 0) {
    n_ports = gSettings.VideoPorts;
    DBG(" user defined from config.plist: %d\n", n_ports);
  } else {
    n_ports = 2; //default
    DBG(" undefined, default to: %d\n", n_ports);
  }
  
  //There are custom properties, injected if set by user
  if (gSettings.NvidiaSingle && (devices_number >=1)) {
    DBG("NVidia: NvidiaSingle :: skip injecting other then first card\n");
    goto done;
  }
  
  if (gSettings.NrAddProperties != 0xFFFE) {
    for (i = 0; i < gSettings.NrAddProperties; i++) {
      if (gSettings.AddProperties[i].Device != DEV_NVIDIA) {
        continue;
      }
      Injected = TRUE;
      devprop_add_value(device,
                        gSettings.AddProperties[i].Key,
                        (UINT8*)gSettings.AddProperties[i].Value,
                        gSettings.AddProperties[i].ValueLen);
    }
    if (Injected) {
      DBG("custom NVIDIA properties injected, continue\n");
      //    return TRUE;
    }
  }
  
  if (gSettings.FakeNVidia) {
    UINT32 FakeID = gSettings.FakeNVidia >> 16;
    DBG("NVidia: FakeID %x:%x\n",gSettings.FakeNVidia & 0xFFFF, FakeID);
    devprop_add_value(device, "device-id", (UINT8*)&FakeID, 4);
    FakeID = gSettings.FakeNVidia & 0xFFFF;
    devprop_add_value(device, "vendor-id", (UINT8*)&FakeID, 4);
  }
  
  if (gSettings.NVCAP[0] != 0) {
    devprop_add_value(device, "NVCAP", &gSettings.NVCAP[0], NVCAP_LEN);
    DBG("set NVCAP: %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x\n",
        gSettings.NVCAP[0], gSettings.NVCAP[1], gSettings.NVCAP[2], gSettings.NVCAP[3],
        gSettings.NVCAP[4], gSettings.NVCAP[5], gSettings.NVCAP[6], gSettings.NVCAP[7],
        gSettings.NVCAP[8], gSettings.NVCAP[9], gSettings.NVCAP[10], gSettings.NVCAP[11],
        gSettings.NVCAP[12], gSettings.NVCAP[13], gSettings.NVCAP[14], gSettings.NVCAP[15],
        gSettings.NVCAP[16], gSettings.NVCAP[17], gSettings.NVCAP[18], gSettings.NVCAP[19]);
  }
  
  if (gSettings.InjectEDID && gSettings.CustomEDID) {
    devprop_add_value(device, "AAPL00,override-no-connect", gSettings.CustomEDID, 128);
  }
  
  if ((devices_number == 1) &&
      ((gSettings.BootDisplay >= 0) && (gSettings.BootDisplay < (INT8)n_ports))) {
    CHAR8 nkey[24];
    AsciiSPrint(nkey, 24, "@%d,AAPL,boot-display", gSettings.BootDisplay);
    devprop_add_value(device, nkey, (UINT8*)&boot_display, 4);
    DBG("Nvidia: BootDisplay: %d\n", gSettings.BootDisplay);
  }
  
  //there are default or calculated properties, can be skipped
  if (gSettings.NoDefaultProperties) {
    DBG("Nvidia: no default properties injected\n");
    goto done;
  }
  
  if (gSettings.BootDisplay < 0) {
    // if not set this is default property
    devprop_add_value(device, "@0,AAPL,boot-display", (UINT8*)&boot_display, 4);
  }/* else {
    DBG("Nvidia: BootDisplay: %x\n", gSettings.BootDisplay);
    }*/
  
  if (gSettings.UseIntelHDMI) {
    devprop_add_value(device, "hda-gfx", (UINT8*)"onboard-2", 10);
  } else {
    devprop_add_value(device, "hda-gfx", (UINT8*)"onboard-1", 10);
  }
  
  if (videoRam != 0) {
    devprop_add_value(device, "VRAM,totalsize", (UINT8*)&videoRam, 8);
  } else {
    DBG("Warning! VideoRAM is not detected and not set\n");
  }
  
  devprop_add_nvidia_template(device, n_ports);
  
  //add HDMI Audio back to nvidia
  //http://forge.voodooprojects.org/p/chameleon/issues/67/
  //AsciiSPrint(nkey, 24, "@%d,connector-type", pnum);
  //devprop_add_value(device, nkey, connector_type_1, 4);
  //end Nvidia HDMI Audio
  
  if (nvPatch == PATCH_ROM_SUCCESS_HAS_LVDS) {
    UINT8 built_in = 0x01;
    devprop_add_value(device, "@0,built-in", &built_in, 1);
    // HDMI is not LVDS
    devprop_add_value(device, "@1,connector-type", connector_type_1, 4);
  } else {
    devprop_add_value(device, "@0,connector-type", connector_type_1, 4);
  }
  
  devprop_add_value(device, "NVPM", default_NVPM, NVPM_LEN);
  devprop_add_value(device, "model", (UINT8*)model, (UINT32)AsciiStrLen(model));
  devprop_add_value(device, "rom-revision", (UINT8*)version_str, (UINT32)AsciiStrLen(version_str));
  
  if (gSettings.NVCAP[0] == 0) {
    devprop_add_value(device, "NVCAP", default_NVCAP, NVCAP_LEN);
    DBG("default NVCAP: %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x%02x%02x\n",
        default_NVCAP[0], default_NVCAP[1], default_NVCAP[2], default_NVCAP[3],
        default_NVCAP[4], default_NVCAP[5], default_NVCAP[6], default_NVCAP[7],
        default_NVCAP[8], default_NVCAP[9], default_NVCAP[10], default_NVCAP[11],
        default_NVCAP[12], default_NVCAP[13], default_NVCAP[14], default_NVCAP[15],
        default_NVCAP[16], default_NVCAP[17], default_NVCAP[18], default_NVCAP[19]);
  }
  
done:
  devices_number++;
  FreePool(version_str);
  if (buffer) {
    FreePool(buffer);
  }
  if (!RomAssigned) {
    FreePool(rom);
  }
  return TRUE;
}
